Merge pull request #1292 from basbl/write-to-stream-support
Support writing to resource handles in all IWriter implementations
This commit is contained in:
commit
8967696095
|
@ -55,7 +55,8 @@
|
|||
"ext-zlib": "*",
|
||||
"markbaker/complex": "^1.4",
|
||||
"markbaker/matrix": "^1.2",
|
||||
"psr/simple-cache": "^1.0"
|
||||
"psr/simple-cache": "^1.0",
|
||||
"maennchen/zipstream-php": "^2.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"dompdf/dompdf": "^0.8.5",
|
||||
|
|
|
@ -4,8 +4,69 @@
|
|||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||
"This file is @generated automatically"
|
||||
],
|
||||
"content-hash": "9c60146d8c78c13d2610a2cec23339a2",
|
||||
"content-hash": "ab06908c3ff8187971def16c578f1ced",
|
||||
"packages": [
|
||||
{
|
||||
"name": "maennchen/zipstream-php",
|
||||
"version": "2.0.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/maennchen/ZipStream-PHP.git",
|
||||
"reference": "9ceee828f9620b2e5c075e551ec7ed8a7035ac95"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/maennchen/ZipStream-PHP/zipball/9ceee828f9620b2e5c075e551ec7ed8a7035ac95",
|
||||
"reference": "9ceee828f9620b2e5c075e551ec7ed8a7035ac95",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"ext-mbstring": "*",
|
||||
"myclabs/php-enum": "^1.5",
|
||||
"php": ">= 7.1",
|
||||
"psr/http-message": "^1.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"ext-zip": "*",
|
||||
"guzzlehttp/guzzle": ">= 6.3",
|
||||
"mikey179/vfsstream": "^1.6",
|
||||
"phpunit/phpunit": ">= 7.5"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"ZipStream\\": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Paul Duncan",
|
||||
"email": "pabs@pablotron.org"
|
||||
},
|
||||
{
|
||||
"name": "Jonatan Männchen",
|
||||
"email": "jonatan@maennchen.ch"
|
||||
},
|
||||
{
|
||||
"name": "Jesse Donat",
|
||||
"email": "donatj@gmail.com"
|
||||
},
|
||||
{
|
||||
"name": "András Kolesár",
|
||||
"email": "kolesar@kolesar.hu"
|
||||
}
|
||||
],
|
||||
"description": "ZipStream is a library for dynamically streaming dynamic zip files from PHP without writing to the disk at all on the server.",
|
||||
"keywords": [
|
||||
"stream",
|
||||
"zip"
|
||||
],
|
||||
"time": "2020-02-23T01:48:39+00:00"
|
||||
},
|
||||
{
|
||||
"name": "markbaker/complex",
|
||||
"version": "1.4.8",
|
||||
|
@ -170,6 +231,102 @@
|
|||
],
|
||||
"time": "2019-10-06T11:29:25+00:00"
|
||||
},
|
||||
{
|
||||
"name": "myclabs/php-enum",
|
||||
"version": "1.7.6",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/myclabs/php-enum.git",
|
||||
"reference": "5f36467c7a87e20fbdc51e524fd8f9d1de80187c"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/myclabs/php-enum/zipball/5f36467c7a87e20fbdc51e524fd8f9d1de80187c",
|
||||
"reference": "5f36467c7a87e20fbdc51e524fd8f9d1de80187c",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"ext-json": "*",
|
||||
"php": ">=7.1"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "^7",
|
||||
"squizlabs/php_codesniffer": "1.*",
|
||||
"vimeo/psalm": "^3.8"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"MyCLabs\\Enum\\": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "PHP Enum contributors",
|
||||
"homepage": "https://github.com/myclabs/php-enum/graphs/contributors"
|
||||
}
|
||||
],
|
||||
"description": "PHP Enum implementation",
|
||||
"homepage": "http://github.com/myclabs/php-enum",
|
||||
"keywords": [
|
||||
"enum"
|
||||
],
|
||||
"time": "2020-02-14T08:15:52+00:00"
|
||||
},
|
||||
{
|
||||
"name": "psr/http-message",
|
||||
"version": "1.0.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/php-fig/http-message.git",
|
||||
"reference": "f6561bf28d520154e4b0ec72be95418abe6d9363"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/php-fig/http-message/zipball/f6561bf28d520154e4b0ec72be95418abe6d9363",
|
||||
"reference": "f6561bf28d520154e4b0ec72be95418abe6d9363",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=5.3.0"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "1.0.x-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Psr\\Http\\Message\\": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "PHP-FIG",
|
||||
"homepage": "http://www.php-fig.org/"
|
||||
}
|
||||
],
|
||||
"description": "Common interface for HTTP messages",
|
||||
"homepage": "https://github.com/php-fig/http-message",
|
||||
"keywords": [
|
||||
"http",
|
||||
"http-message",
|
||||
"psr",
|
||||
"psr-7",
|
||||
"request",
|
||||
"response"
|
||||
],
|
||||
"time": "2016-08-06T14:39:51+00:00"
|
||||
},
|
||||
{
|
||||
"name": "psr/simple-cache",
|
||||
"version": "1.0.1",
|
||||
|
@ -323,6 +480,12 @@
|
|||
"Xdebug",
|
||||
"performance"
|
||||
],
|
||||
"funding": [
|
||||
{
|
||||
"url": "https://packagist.com",
|
||||
"type": "custom"
|
||||
}
|
||||
],
|
||||
"time": "2020-03-01T12:26:26+00:00"
|
||||
},
|
||||
{
|
||||
|
@ -667,6 +830,12 @@
|
|||
}
|
||||
],
|
||||
"description": "A tool to automatically fix PHP code style",
|
||||
"funding": [
|
||||
{
|
||||
"url": "https://github.com/keradus",
|
||||
"type": "github"
|
||||
}
|
||||
],
|
||||
"time": "2020-04-15T18:51:10+00:00"
|
||||
},
|
||||
{
|
||||
|
@ -1703,6 +1872,16 @@
|
|||
"testing",
|
||||
"xunit"
|
||||
],
|
||||
"funding": [
|
||||
{
|
||||
"url": "https://phpunit.de/donate.html",
|
||||
"type": "custom"
|
||||
},
|
||||
{
|
||||
"url": "https://github.com/sebastianbergmann",
|
||||
"type": "github"
|
||||
}
|
||||
],
|
||||
"time": "2020-04-23T04:39:42+00:00"
|
||||
},
|
||||
{
|
||||
|
@ -2566,6 +2745,12 @@
|
|||
"fpdi",
|
||||
"pdf"
|
||||
],
|
||||
"funding": [
|
||||
{
|
||||
"url": "https://tidelift.com/funding/github/packagist/setasign/fpdi",
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2020-03-23T15:53:59+00:00"
|
||||
},
|
||||
{
|
||||
|
@ -2693,6 +2878,20 @@
|
|||
],
|
||||
"description": "Symfony Console Component",
|
||||
"homepage": "https://symfony.com",
|
||||
"funding": [
|
||||
{
|
||||
"url": "https://symfony.com/sponsor",
|
||||
"type": "custom"
|
||||
},
|
||||
{
|
||||
"url": "https://github.com/fabpot",
|
||||
"type": "github"
|
||||
},
|
||||
{
|
||||
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2020-03-30T11:42:42+00:00"
|
||||
},
|
||||
{
|
||||
|
@ -2763,6 +2962,20 @@
|
|||
],
|
||||
"description": "Symfony EventDispatcher Component",
|
||||
"homepage": "https://symfony.com",
|
||||
"funding": [
|
||||
{
|
||||
"url": "https://symfony.com/sponsor",
|
||||
"type": "custom"
|
||||
},
|
||||
{
|
||||
"url": "https://github.com/fabpot",
|
||||
"type": "github"
|
||||
},
|
||||
{
|
||||
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2020-03-27T16:56:45+00:00"
|
||||
},
|
||||
{
|
||||
|
@ -2871,6 +3084,20 @@
|
|||
],
|
||||
"description": "Symfony Filesystem Component",
|
||||
"homepage": "https://symfony.com",
|
||||
"funding": [
|
||||
{
|
||||
"url": "https://symfony.com/sponsor",
|
||||
"type": "custom"
|
||||
},
|
||||
{
|
||||
"url": "https://github.com/fabpot",
|
||||
"type": "github"
|
||||
},
|
||||
{
|
||||
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2020-03-27T16:56:45+00:00"
|
||||
},
|
||||
{
|
||||
|
@ -2920,6 +3147,20 @@
|
|||
],
|
||||
"description": "Symfony Finder Component",
|
||||
"homepage": "https://symfony.com",
|
||||
"funding": [
|
||||
{
|
||||
"url": "https://symfony.com/sponsor",
|
||||
"type": "custom"
|
||||
},
|
||||
{
|
||||
"url": "https://github.com/fabpot",
|
||||
"type": "github"
|
||||
},
|
||||
{
|
||||
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2020-03-27T16:56:45+00:00"
|
||||
},
|
||||
{
|
||||
|
@ -2974,6 +3215,20 @@
|
|||
"configuration",
|
||||
"options"
|
||||
],
|
||||
"funding": [
|
||||
{
|
||||
"url": "https://symfony.com/sponsor",
|
||||
"type": "custom"
|
||||
},
|
||||
{
|
||||
"url": "https://github.com/fabpot",
|
||||
"type": "github"
|
||||
},
|
||||
{
|
||||
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2020-03-27T16:56:45+00:00"
|
||||
},
|
||||
{
|
||||
|
@ -3032,6 +3287,20 @@
|
|||
"polyfill",
|
||||
"portable"
|
||||
],
|
||||
"funding": [
|
||||
{
|
||||
"url": "https://symfony.com/sponsor",
|
||||
"type": "custom"
|
||||
},
|
||||
{
|
||||
"url": "https://github.com/fabpot",
|
||||
"type": "github"
|
||||
},
|
||||
{
|
||||
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2020-02-27T09:26:54+00:00"
|
||||
},
|
||||
{
|
||||
|
@ -3091,6 +3360,20 @@
|
|||
"portable",
|
||||
"shim"
|
||||
],
|
||||
"funding": [
|
||||
{
|
||||
"url": "https://symfony.com/sponsor",
|
||||
"type": "custom"
|
||||
},
|
||||
{
|
||||
"url": "https://github.com/fabpot",
|
||||
"type": "github"
|
||||
},
|
||||
{
|
||||
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2020-03-09T19:04:49+00:00"
|
||||
},
|
||||
{
|
||||
|
@ -3205,6 +3488,20 @@
|
|||
"portable",
|
||||
"shim"
|
||||
],
|
||||
"funding": [
|
||||
{
|
||||
"url": "https://symfony.com/sponsor",
|
||||
"type": "custom"
|
||||
},
|
||||
{
|
||||
"url": "https://github.com/fabpot",
|
||||
"type": "github"
|
||||
},
|
||||
{
|
||||
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2020-02-27T09:26:54+00:00"
|
||||
},
|
||||
{
|
||||
|
@ -3263,6 +3560,20 @@
|
|||
"portable",
|
||||
"shim"
|
||||
],
|
||||
"funding": [
|
||||
{
|
||||
"url": "https://symfony.com/sponsor",
|
||||
"type": "custom"
|
||||
},
|
||||
{
|
||||
"url": "https://github.com/fabpot",
|
||||
"type": "github"
|
||||
},
|
||||
{
|
||||
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2020-02-27T09:26:54+00:00"
|
||||
},
|
||||
{
|
||||
|
@ -3312,6 +3623,20 @@
|
|||
],
|
||||
"description": "Symfony Process Component",
|
||||
"homepage": "https://symfony.com",
|
||||
"funding": [
|
||||
{
|
||||
"url": "https://symfony.com/sponsor",
|
||||
"type": "custom"
|
||||
},
|
||||
{
|
||||
"url": "https://github.com/fabpot",
|
||||
"type": "github"
|
||||
},
|
||||
{
|
||||
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2020-03-27T16:56:45+00:00"
|
||||
},
|
||||
{
|
||||
|
@ -3420,6 +3745,20 @@
|
|||
],
|
||||
"description": "Symfony Stopwatch Component",
|
||||
"homepage": "https://symfony.com",
|
||||
"funding": [
|
||||
{
|
||||
"url": "https://symfony.com/sponsor",
|
||||
"type": "custom"
|
||||
},
|
||||
{
|
||||
"url": "https://github.com/fabpot",
|
||||
"type": "github"
|
||||
},
|
||||
{
|
||||
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2020-03-27T16:56:45+00:00"
|
||||
},
|
||||
{
|
||||
|
@ -3594,5 +3933,6 @@
|
|||
"ext-zip": "*",
|
||||
"ext-zlib": "*"
|
||||
},
|
||||
"platform-dev": []
|
||||
"platform-dev": [],
|
||||
"plugin-api-version": "1.1.0"
|
||||
}
|
||||
|
|
|
@ -22,7 +22,6 @@ namespace PhpOffice\PhpSpreadsheet\Shared\OLE\PPS;
|
|||
//
|
||||
use PhpOffice\PhpSpreadsheet\Shared\OLE;
|
||||
use PhpOffice\PhpSpreadsheet\Shared\OLE\PPS;
|
||||
use PhpOffice\PhpSpreadsheet\Writer\Exception as WriterException;
|
||||
|
||||
/**
|
||||
* Class for creating Root PPS's for OLE containers.
|
||||
|
@ -33,23 +32,11 @@ use PhpOffice\PhpSpreadsheet\Writer\Exception as WriterException;
|
|||
*/
|
||||
class Root extends PPS
|
||||
{
|
||||
/**
|
||||
* Directory for temporary files.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $tempDirectory;
|
||||
|
||||
/**
|
||||
* @var resource
|
||||
*/
|
||||
private $fileHandle;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $tempFilename;
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
|
@ -67,8 +54,6 @@ class Root extends PPS
|
|||
*/
|
||||
public function __construct($time_1st, $time_2nd, $raChild)
|
||||
{
|
||||
$this->tempDirectory = \PhpOffice\PhpSpreadsheet\Shared\File::sysGetTempDir();
|
||||
|
||||
parent::__construct(null, OLE::ascToUcs('Root Entry'), OLE::OLE_PPS_TYPE_ROOT, null, null, null, $time_1st, $time_2nd, null, $raChild);
|
||||
}
|
||||
|
||||
|
@ -79,14 +64,14 @@ class Root extends PPS
|
|||
* If a resource pointer to a stream created by fopen() is passed
|
||||
* it will be used, but you have to close such stream by yourself.
|
||||
*
|
||||
* @param resource|string $filename the name of the file or stream where to save the OLE container
|
||||
*
|
||||
* @throws WriterException
|
||||
* @param resource $fileHandle the name of the file or stream where to save the OLE container
|
||||
*
|
||||
* @return bool true on success
|
||||
*/
|
||||
public function save($filename)
|
||||
public function save($fileHandle)
|
||||
{
|
||||
$this->fileHandle = $fileHandle;
|
||||
|
||||
// Initial Setting for saving
|
||||
$this->bigBlockSize = pow(
|
||||
2,
|
||||
|
@ -97,23 +82,6 @@ class Root extends PPS
|
|||
(isset($this->smallBlockSize)) ? self::adjust2($this->smallBlockSize) : 6
|
||||
);
|
||||
|
||||
if (is_resource($filename)) {
|
||||
$this->fileHandle = $filename;
|
||||
} elseif ($filename == '-' || $filename == '') {
|
||||
if ($this->tempDirectory === null) {
|
||||
$this->tempDirectory = \PhpOffice\PhpSpreadsheet\Shared\File::sysGetTempDir();
|
||||
}
|
||||
$this->tempFilename = tempnam($this->tempDirectory, 'OLE_PPS_Root');
|
||||
$this->fileHandle = fopen($this->tempFilename, 'w+b');
|
||||
if ($this->fileHandle == false) {
|
||||
throw new WriterException("Can't create temporary file.");
|
||||
}
|
||||
} else {
|
||||
$this->fileHandle = fopen($filename, 'wb');
|
||||
}
|
||||
if ($this->fileHandle == false) {
|
||||
throw new WriterException("Can't open $filename. It may be in use or protected.");
|
||||
}
|
||||
// Make an array of PPS's (for Save)
|
||||
$aList = [];
|
||||
PPS::_savePpsSetPnt($aList, [$this]);
|
||||
|
@ -132,10 +100,6 @@ class Root extends PPS
|
|||
// Write Big Block Depot and BDList and Adding Header informations
|
||||
$this->_saveBbd($iSBDcnt, $iBBcnt, $iPPScnt);
|
||||
|
||||
if (!is_resource($filename)) {
|
||||
fclose($this->fileHandle);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -35,6 +35,16 @@ abstract class BaseWriter implements IWriter
|
|||
*/
|
||||
private $diskCachingDirectory = './';
|
||||
|
||||
/**
|
||||
* @var resource
|
||||
*/
|
||||
protected $fileHandle;
|
||||
|
||||
/**
|
||||
* @var bool
|
||||
*/
|
||||
private $shouldCloseFile;
|
||||
|
||||
public function getIncludeCharts()
|
||||
{
|
||||
return $this->includeCharts;
|
||||
|
@ -83,4 +93,39 @@ abstract class BaseWriter implements IWriter
|
|||
{
|
||||
return $this->diskCachingDirectory;
|
||||
}
|
||||
|
||||
/**
|
||||
* Open file handle.
|
||||
*
|
||||
* @param resource|string $filename
|
||||
*/
|
||||
public function openFileHandle($filename): void
|
||||
{
|
||||
if (is_resource($filename)) {
|
||||
$this->fileHandle = $filename;
|
||||
$this->shouldCloseFile = false;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$fileHandle = fopen($filename, 'wb+');
|
||||
if ($fileHandle === false) {
|
||||
throw new Exception('Could not open file ' . $filename . ' for writing.');
|
||||
}
|
||||
|
||||
$this->fileHandle = $fileHandle;
|
||||
$this->shouldCloseFile = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Close file handle only we opened it ourselves.
|
||||
*/
|
||||
protected function maybeCloseFileHandle(): void
|
||||
{
|
||||
if ($this->shouldCloseFile) {
|
||||
if (!fclose($this->fileHandle)) {
|
||||
throw new Exception('Could not close file after writing.');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@ namespace PhpOffice\PhpSpreadsheet\Writer;
|
|||
|
||||
use PhpOffice\PhpSpreadsheet\Calculation\Calculation;
|
||||
use PhpOffice\PhpSpreadsheet\Spreadsheet;
|
||||
use PhpOffice\PhpSpreadsheet\Writer\Exception as WriterException;
|
||||
|
||||
class Csv extends BaseWriter
|
||||
{
|
||||
|
@ -77,7 +78,7 @@ class Csv extends BaseWriter
|
|||
/**
|
||||
* Save PhpSpreadsheet to file.
|
||||
*
|
||||
* @param string $pFilename
|
||||
* @param resource|string $pFilename
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
|
@ -92,9 +93,14 @@ class Csv extends BaseWriter
|
|||
Calculation::setArrayReturnType(Calculation::RETURN_ARRAY_AS_VALUE);
|
||||
|
||||
// Open file
|
||||
$fileHandle = fopen($pFilename, 'wb+');
|
||||
if (is_resource($pFilename)) {
|
||||
$fileHandle = $pFilename;
|
||||
} else {
|
||||
$fileHandle = fopen($pFilename, 'wb+');
|
||||
}
|
||||
|
||||
if ($fileHandle === false) {
|
||||
throw new Exception("Could not open file $pFilename for writing.");
|
||||
throw new WriterException("Could not open file $pFilename for writing.");
|
||||
}
|
||||
|
||||
if ($this->excelCompatibility) {
|
||||
|
@ -125,9 +131,6 @@ class Csv extends BaseWriter
|
|||
$this->writeLine($fileHandle, $cellsArray[0]);
|
||||
}
|
||||
|
||||
// Close file
|
||||
fclose($fileHandle);
|
||||
|
||||
Calculation::setArrayReturnType($saveArrayReturnType);
|
||||
Calculation::getInstance($this->spreadsheet)->getDebugLog()->setWriteDebugLog($saveDebugLog);
|
||||
}
|
||||
|
|
|
@ -146,7 +146,7 @@ class Html extends BaseWriter
|
|||
/**
|
||||
* Save Spreadsheet to file.
|
||||
*
|
||||
* @param string $pFilename
|
||||
* @param resource|string $pFilename
|
||||
*
|
||||
* @throws WriterException
|
||||
*/
|
||||
|
@ -164,27 +164,23 @@ class Html extends BaseWriter
|
|||
$this->buildCSS(!$this->useInlineCss);
|
||||
|
||||
// Open file
|
||||
$fileHandle = fopen($pFilename, 'wb+');
|
||||
if ($fileHandle === false) {
|
||||
throw new WriterException("Could not open file $pFilename for writing.");
|
||||
}
|
||||
$this->openFileHandle($pFilename);
|
||||
|
||||
// Write headers
|
||||
fwrite($fileHandle, $this->generateHTMLHeader(!$this->useInlineCss));
|
||||
fwrite($this->fileHandle, $this->generateHTMLHeader(!$this->useInlineCss));
|
||||
|
||||
// Write navigation (tabs)
|
||||
if ((!$this->isPdf) && ($this->generateSheetNavigationBlock)) {
|
||||
fwrite($fileHandle, $this->generateNavigation());
|
||||
fwrite($this->fileHandle, $this->generateNavigation());
|
||||
}
|
||||
|
||||
// Write data
|
||||
fwrite($fileHandle, $this->generateSheetData());
|
||||
fwrite($this->fileHandle, $this->generateSheetData());
|
||||
|
||||
// Write footer
|
||||
fwrite($fileHandle, $this->generateHTMLFooter());
|
||||
fwrite($this->fileHandle, $this->generateHTMLFooter());
|
||||
|
||||
// Close file
|
||||
fclose($fileHandle);
|
||||
$this->maybeCloseFileHandle();
|
||||
|
||||
Calculation::setArrayReturnType($saveArrayReturnType);
|
||||
Calculation::getInstance($this->spreadsheet)->getDebugLog()->setWriteDebugLog($saveDebugLog);
|
||||
|
|
|
@ -59,7 +59,7 @@ interface IWriter
|
|||
/**
|
||||
* Save PhpSpreadsheet to file.
|
||||
*
|
||||
* @param string $pFilename Name of the file to save
|
||||
* @param resource|string $pFilename Name of the file to save
|
||||
*
|
||||
* @throws \PhpOffice\PhpSpreadsheet\Writer\Exception
|
||||
*/
|
||||
|
|
|
@ -12,7 +12,9 @@ use PhpOffice\PhpSpreadsheet\Writer\Ods\Mimetype;
|
|||
use PhpOffice\PhpSpreadsheet\Writer\Ods\Settings;
|
||||
use PhpOffice\PhpSpreadsheet\Writer\Ods\Styles;
|
||||
use PhpOffice\PhpSpreadsheet\Writer\Ods\Thumbnails;
|
||||
use ZipArchive;
|
||||
use ZipStream\Exception\OverflowException;
|
||||
use ZipStream\Option\Archive;
|
||||
use ZipStream\ZipStream;
|
||||
|
||||
class Ods extends BaseWriter
|
||||
{
|
||||
|
@ -73,7 +75,7 @@ class Ods extends BaseWriter
|
|||
/**
|
||||
* Save PhpSpreadsheet to file.
|
||||
*
|
||||
* @param string $pFilename
|
||||
* @param resource|string $pFilename
|
||||
*
|
||||
* @throws WriterException
|
||||
*/
|
||||
|
@ -86,64 +88,48 @@ class Ods extends BaseWriter
|
|||
// garbage collect
|
||||
$this->spreadSheet->garbageCollect();
|
||||
|
||||
// If $pFilename is php://output or php://stdout, make it a temporary file...
|
||||
$originalFilename = $pFilename;
|
||||
if (strtolower($pFilename) == 'php://output' || strtolower($pFilename) == 'php://stdout') {
|
||||
$pFilename = @tempnam(File::sysGetTempDir(), 'phpxltmp');
|
||||
if ($pFilename == '') {
|
||||
$pFilename = $originalFilename;
|
||||
}
|
||||
}
|
||||
$this->openFileHandle($pFilename);
|
||||
|
||||
$zip = $this->createZip($pFilename);
|
||||
$zip = $this->createZip();
|
||||
|
||||
$zip->addFromString('META-INF/manifest.xml', $this->getWriterPart('meta_inf')->writeManifest());
|
||||
$zip->addFromString('Thumbnails/thumbnail.png', $this->getWriterPart('thumbnails')->writeThumbnail());
|
||||
$zip->addFromString('content.xml', $this->getWriterPart('content')->write());
|
||||
$zip->addFromString('meta.xml', $this->getWriterPart('meta')->write());
|
||||
$zip->addFromString('mimetype', $this->getWriterPart('mimetype')->write());
|
||||
$zip->addFromString('settings.xml', $this->getWriterPart('settings')->write());
|
||||
$zip->addFromString('styles.xml', $this->getWriterPart('styles')->write());
|
||||
$zip->addFile('META-INF/manifest.xml', $this->getWriterPart('meta_inf')->writeManifest());
|
||||
$zip->addFile('Thumbnails/thumbnail.png', $this->getWriterPart('thumbnails')->writeThumbnail());
|
||||
$zip->addFile('content.xml', $this->getWriterPart('content')->write());
|
||||
$zip->addFile('meta.xml', $this->getWriterPart('meta')->write());
|
||||
$zip->addFile('mimetype', $this->getWriterPart('mimetype')->write());
|
||||
$zip->addFile('settings.xml', $this->getWriterPart('settings')->write());
|
||||
$zip->addFile('styles.xml', $this->getWriterPart('styles')->write());
|
||||
|
||||
// Close file
|
||||
if ($zip->close() === false) {
|
||||
throw new WriterException("Could not close zip file $pFilename.");
|
||||
try {
|
||||
$zip->finish();
|
||||
} catch (OverflowException $e) {
|
||||
throw new WriterException('Could not close resource.');
|
||||
}
|
||||
|
||||
// If a temporary file was used, copy it to the correct file stream
|
||||
if ($originalFilename != $pFilename) {
|
||||
if (copy($pFilename, $originalFilename) === false) {
|
||||
throw new WriterException("Could not copy temporary zip file $pFilename to $originalFilename.");
|
||||
}
|
||||
@unlink($pFilename);
|
||||
}
|
||||
$this->maybeCloseFileHandle();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create zip object.
|
||||
*
|
||||
* @param string $pFilename
|
||||
*
|
||||
* @throws WriterException
|
||||
*
|
||||
* @return ZipArchive
|
||||
* @return ZipStream
|
||||
*/
|
||||
private function createZip($pFilename)
|
||||
private function createZip()
|
||||
{
|
||||
// Create new ZIP file and open it for writing
|
||||
$zip = new ZipArchive();
|
||||
|
||||
if (file_exists($pFilename)) {
|
||||
unlink($pFilename);
|
||||
}
|
||||
// Try opening the ZIP file
|
||||
if ($zip->open($pFilename, ZipArchive::OVERWRITE) !== true) {
|
||||
if ($zip->open($pFilename, ZipArchive::CREATE) !== true) {
|
||||
throw new WriterException("Could not open $pFilename for writing.");
|
||||
}
|
||||
if (!is_resource($this->fileHandle)) {
|
||||
throw new WriterException('Could not open resource for writing.');
|
||||
}
|
||||
|
||||
return $zip;
|
||||
// Create new ZIP stream
|
||||
$options = new Archive();
|
||||
$options->setEnableZip64(false);
|
||||
$options->setOutputStream($this->fileHandle);
|
||||
|
||||
return new ZipStream(null, $options);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -255,28 +255,22 @@ abstract class Pdf extends Html
|
|||
Calculation::setArrayReturnType(Calculation::RETURN_ARRAY_AS_VALUE);
|
||||
|
||||
// Open file
|
||||
$fileHandle = fopen($pFilename, 'w');
|
||||
if ($fileHandle === false) {
|
||||
throw new WriterException("Could not open file $pFilename for writing.");
|
||||
}
|
||||
$this->openFileHandle($pFilename);
|
||||
|
||||
// Set PDF
|
||||
$this->isPdf = true;
|
||||
// Build CSS
|
||||
$this->buildCSS(true);
|
||||
|
||||
return $fileHandle;
|
||||
return $this->fileHandle;
|
||||
}
|
||||
|
||||
/**
|
||||
* Save PhpSpreadsheet to PDF file, post-save.
|
||||
*
|
||||
* @param resource $fileHandle
|
||||
*/
|
||||
protected function restoreStateAfterSave($fileHandle)
|
||||
protected function restoreStateAfterSave(): void
|
||||
{
|
||||
// Close file
|
||||
fclose($fileHandle);
|
||||
$this->maybeCloseFileHandle();
|
||||
|
||||
Calculation::setArrayReturnType($this->saveArrayReturnType);
|
||||
}
|
||||
|
|
|
@ -73,6 +73,6 @@ class Dompdf extends Pdf
|
|||
// Write to file
|
||||
fwrite($fileHandle, $pdf->output());
|
||||
|
||||
parent::restoreStateAfterSave($fileHandle);
|
||||
parent::restoreStateAfterSave();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -65,7 +65,7 @@ class Mpdf extends Pdf
|
|||
}
|
||||
|
||||
// Create PDF
|
||||
$config = ['tempDir' => $this->tempDir];
|
||||
$config = ['tempDir' => $this->tempDir . '/mpdf'];
|
||||
$pdf = $this->createExternalWriterInstance($config);
|
||||
$ortmp = $orientation;
|
||||
$pdf->_setPageSize(strtoupper($paperSize), $ortmp);
|
||||
|
@ -95,7 +95,7 @@ class Mpdf extends Pdf
|
|||
// Write to file
|
||||
fwrite($fileHandle, $pdf->Output('', 'S'));
|
||||
|
||||
parent::restoreStateAfterSave($fileHandle);
|
||||
parent::restoreStateAfterSave();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -93,6 +93,6 @@ class Tcpdf extends Pdf
|
|||
// Write to file
|
||||
fwrite($fileHandle, $pdf->output($pFilename, 'S'));
|
||||
|
||||
parent::restoreStateAfterSave($fileHandle);
|
||||
parent::restoreStateAfterSave();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -115,7 +115,7 @@ class Xls extends BaseWriter
|
|||
/**
|
||||
* Save Spreadsheet to file.
|
||||
*
|
||||
* @param string $pFilename
|
||||
* @param resource|string $pFilename
|
||||
*
|
||||
* @throws \PhpOffice\PhpSpreadsheet\Writer\Exception
|
||||
*/
|
||||
|
@ -221,7 +221,9 @@ class Xls extends BaseWriter
|
|||
|
||||
$root = new Root(time(), time(), $arrRootData);
|
||||
// save the OLE file
|
||||
$root->save($pFilename);
|
||||
$this->openFileHandle($pFilename);
|
||||
$root->save($this->fileHandle);
|
||||
$this->maybeCloseFileHandle();
|
||||
|
||||
Functions::setReturnDateType($saveDateReturnType);
|
||||
Calculation::getInstance($this->spreadsheet)->getDebugLog()->setWriteDebugLog($saveDebugLog);
|
||||
|
|
|
@ -24,6 +24,9 @@ use PhpOffice\PhpSpreadsheet\Writer\Xlsx\Theme;
|
|||
use PhpOffice\PhpSpreadsheet\Writer\Xlsx\Workbook;
|
||||
use PhpOffice\PhpSpreadsheet\Writer\Xlsx\Worksheet;
|
||||
use ZipArchive;
|
||||
use ZipStream\Exception\OverflowException;
|
||||
use ZipStream\Option\Archive;
|
||||
use ZipStream\ZipStream;
|
||||
|
||||
class Xlsx extends BaseWriter
|
||||
{
|
||||
|
@ -166,7 +169,7 @@ class Xlsx extends BaseWriter
|
|||
/**
|
||||
* Save PhpSpreadsheet to file.
|
||||
*
|
||||
* @param string $pFilename
|
||||
* @param resource|string $pFilename
|
||||
*
|
||||
* @throws WriterException
|
||||
*/
|
||||
|
@ -176,14 +179,7 @@ class Xlsx extends BaseWriter
|
|||
// garbage collect
|
||||
$this->spreadSheet->garbageCollect();
|
||||
|
||||
// If $pFilename is php://output or php://stdout, make it a temporary file...
|
||||
$originalFilename = $pFilename;
|
||||
if (strtolower($pFilename) == 'php://output' || strtolower($pFilename) == 'php://stdout') {
|
||||
$pFilename = @tempnam(File::sysGetTempDir(), 'phpxltmp');
|
||||
if ($pFilename == '') {
|
||||
$pFilename = $originalFilename;
|
||||
}
|
||||
}
|
||||
$this->openFileHandle($pFilename);
|
||||
|
||||
$saveDebugLog = Calculation::getInstance($this->spreadSheet)->getDebugLog()->getWriteDebugLog();
|
||||
Calculation::getInstance($this->spreadSheet)->getDebugLog()->setWriteDebugLog(false);
|
||||
|
@ -207,83 +203,77 @@ class Xlsx extends BaseWriter
|
|||
// Create drawing dictionary
|
||||
$this->drawingHashTable->addFromSource($this->getWriterPart('Drawing')->allDrawings($this->spreadSheet));
|
||||
|
||||
$zip = new ZipArchive();
|
||||
$options = new Archive();
|
||||
$options->setEnableZip64(false);
|
||||
$options->setOutputStream($this->fileHandle);
|
||||
|
||||
if (file_exists($pFilename)) {
|
||||
unlink($pFilename);
|
||||
}
|
||||
// Try opening the ZIP file
|
||||
if ($zip->open($pFilename, ZipArchive::OVERWRITE) !== true) {
|
||||
if ($zip->open($pFilename, ZipArchive::CREATE) !== true) {
|
||||
throw new WriterException('Could not open ' . $pFilename . ' for writing.');
|
||||
}
|
||||
}
|
||||
$zip = new ZipStream(null, $options);
|
||||
|
||||
// Add [Content_Types].xml to ZIP file
|
||||
$zip->addFromString('[Content_Types].xml', $this->getWriterPart('ContentTypes')->writeContentTypes($this->spreadSheet, $this->includeCharts));
|
||||
$zip->addFile('[Content_Types].xml', $this->getWriterPart('ContentTypes')->writeContentTypes($this->spreadSheet, $this->includeCharts));
|
||||
|
||||
//if hasMacros, add the vbaProject.bin file, Certificate file(if exists)
|
||||
if ($this->spreadSheet->hasMacros()) {
|
||||
$macrosCode = $this->spreadSheet->getMacrosCode();
|
||||
if ($macrosCode !== null) {
|
||||
// we have the code ?
|
||||
$zip->addFromString('xl/vbaProject.bin', $macrosCode); //allways in 'xl', allways named vbaProject.bin
|
||||
$zip->addFile('xl/vbaProject.bin', $macrosCode); //allways in 'xl', allways named vbaProject.bin
|
||||
if ($this->spreadSheet->hasMacrosCertificate()) {
|
||||
//signed macros ?
|
||||
// Yes : add the certificate file and the related rels file
|
||||
$zip->addFromString('xl/vbaProjectSignature.bin', $this->spreadSheet->getMacrosCertificate());
|
||||
$zip->addFromString('xl/_rels/vbaProject.bin.rels', $this->getWriterPart('RelsVBA')->writeVBARelationships($this->spreadSheet));
|
||||
$zip->addFile('xl/vbaProjectSignature.bin', $this->spreadSheet->getMacrosCertificate());
|
||||
$zip->addFile('xl/_rels/vbaProject.bin.rels', $this->getWriterPart('RelsVBA')->writeVBARelationships($this->spreadSheet));
|
||||
}
|
||||
}
|
||||
}
|
||||
//a custom UI in this workbook ? add it ("base" xml and additional objects (pictures) and rels)
|
||||
if ($this->spreadSheet->hasRibbon()) {
|
||||
$tmpRibbonTarget = $this->spreadSheet->getRibbonXMLData('target');
|
||||
$zip->addFromString($tmpRibbonTarget, $this->spreadSheet->getRibbonXMLData('data'));
|
||||
$zip->addFile($tmpRibbonTarget, $this->spreadSheet->getRibbonXMLData('data'));
|
||||
if ($this->spreadSheet->hasRibbonBinObjects()) {
|
||||
$tmpRootPath = dirname($tmpRibbonTarget) . '/';
|
||||
$ribbonBinObjects = $this->spreadSheet->getRibbonBinObjects('data'); //the files to write
|
||||
foreach ($ribbonBinObjects as $aPath => $aContent) {
|
||||
$zip->addFromString($tmpRootPath . $aPath, $aContent);
|
||||
$zip->addFile($tmpRootPath . $aPath, $aContent);
|
||||
}
|
||||
//the rels for files
|
||||
$zip->addFromString($tmpRootPath . '_rels/' . basename($tmpRibbonTarget) . '.rels', $this->getWriterPart('RelsRibbonObjects')->writeRibbonRelationships($this->spreadSheet));
|
||||
$zip->addFile($tmpRootPath . '_rels/' . basename($tmpRibbonTarget) . '.rels', $this->getWriterPart('RelsRibbonObjects')->writeRibbonRelationships($this->spreadSheet));
|
||||
}
|
||||
}
|
||||
|
||||
// Add relationships to ZIP file
|
||||
$zip->addFromString('_rels/.rels', $this->getWriterPart('Rels')->writeRelationships($this->spreadSheet));
|
||||
$zip->addFromString('xl/_rels/workbook.xml.rels', $this->getWriterPart('Rels')->writeWorkbookRelationships($this->spreadSheet));
|
||||
$zip->addFile('_rels/.rels', $this->getWriterPart('Rels')->writeRelationships($this->spreadSheet));
|
||||
$zip->addFile('xl/_rels/workbook.xml.rels', $this->getWriterPart('Rels')->writeWorkbookRelationships($this->spreadSheet));
|
||||
|
||||
// Add document properties to ZIP file
|
||||
$zip->addFromString('docProps/app.xml', $this->getWriterPart('DocProps')->writeDocPropsApp($this->spreadSheet));
|
||||
$zip->addFromString('docProps/core.xml', $this->getWriterPart('DocProps')->writeDocPropsCore($this->spreadSheet));
|
||||
$zip->addFile('docProps/app.xml', $this->getWriterPart('DocProps')->writeDocPropsApp($this->spreadSheet));
|
||||
$zip->addFile('docProps/core.xml', $this->getWriterPart('DocProps')->writeDocPropsCore($this->spreadSheet));
|
||||
$customPropertiesPart = $this->getWriterPart('DocProps')->writeDocPropsCustom($this->spreadSheet);
|
||||
if ($customPropertiesPart !== null) {
|
||||
$zip->addFromString('docProps/custom.xml', $customPropertiesPart);
|
||||
$zip->addFile('docProps/custom.xml', $customPropertiesPart);
|
||||
}
|
||||
|
||||
// Add theme to ZIP file
|
||||
$zip->addFromString('xl/theme/theme1.xml', $this->getWriterPart('Theme')->writeTheme($this->spreadSheet));
|
||||
$zip->addFile('xl/theme/theme1.xml', $this->getWriterPart('Theme')->writeTheme($this->spreadSheet));
|
||||
|
||||
// Add string table to ZIP file
|
||||
$zip->addFromString('xl/sharedStrings.xml', $this->getWriterPart('StringTable')->writeStringTable($this->stringTable));
|
||||
$zip->addFile('xl/sharedStrings.xml', $this->getWriterPart('StringTable')->writeStringTable($this->stringTable));
|
||||
|
||||
// Add styles to ZIP file
|
||||
$zip->addFromString('xl/styles.xml', $this->getWriterPart('Style')->writeStyles($this->spreadSheet));
|
||||
$zip->addFile('xl/styles.xml', $this->getWriterPart('Style')->writeStyles($this->spreadSheet));
|
||||
|
||||
// Add workbook to ZIP file
|
||||
$zip->addFromString('xl/workbook.xml', $this->getWriterPart('Workbook')->writeWorkbook($this->spreadSheet, $this->preCalculateFormulas));
|
||||
$zip->addFile('xl/workbook.xml', $this->getWriterPart('Workbook')->writeWorkbook($this->spreadSheet, $this->preCalculateFormulas));
|
||||
|
||||
$chartCount = 0;
|
||||
// Add worksheets
|
||||
for ($i = 0; $i < $this->spreadSheet->getSheetCount(); ++$i) {
|
||||
$zip->addFromString('xl/worksheets/sheet' . ($i + 1) . '.xml', $this->getWriterPart('Worksheet')->writeWorksheet($this->spreadSheet->getSheet($i), $this->stringTable, $this->includeCharts));
|
||||
$zip->addFile('xl/worksheets/sheet' . ($i + 1) . '.xml', $this->getWriterPart('Worksheet')->writeWorksheet($this->spreadSheet->getSheet($i), $this->stringTable, $this->includeCharts));
|
||||
if ($this->includeCharts) {
|
||||
$charts = $this->spreadSheet->getSheet($i)->getChartCollection();
|
||||
if (count($charts) > 0) {
|
||||
foreach ($charts as $chart) {
|
||||
$zip->addFromString('xl/charts/chart' . ($chartCount + 1) . '.xml', $this->getWriterPart('Chart')->writeChart($chart, $this->preCalculateFormulas));
|
||||
$zip->addFile('xl/charts/chart' . ($chartCount + 1) . '.xml', $this->getWriterPart('Chart')->writeChart($chart, $this->preCalculateFormulas));
|
||||
++$chartCount;
|
||||
}
|
||||
}
|
||||
|
@ -294,19 +284,19 @@ class Xlsx extends BaseWriter
|
|||
// Add worksheet relationships (drawings, ...)
|
||||
for ($i = 0; $i < $this->spreadSheet->getSheetCount(); ++$i) {
|
||||
// Add relationships
|
||||
$zip->addFromString('xl/worksheets/_rels/sheet' . ($i + 1) . '.xml.rels', $this->getWriterPart('Rels')->writeWorksheetRelationships($this->spreadSheet->getSheet($i), ($i + 1), $this->includeCharts));
|
||||
$zip->addFile('xl/worksheets/_rels/sheet' . ($i + 1) . '.xml.rels', $this->getWriterPart('Rels')->writeWorksheetRelationships($this->spreadSheet->getSheet($i), ($i + 1), $this->includeCharts));
|
||||
|
||||
// Add unparsedLoadedData
|
||||
$sheetCodeName = $this->spreadSheet->getSheet($i)->getCodeName();
|
||||
$unparsedLoadedData = $this->spreadSheet->getUnparsedLoadedData();
|
||||
if (isset($unparsedLoadedData['sheets'][$sheetCodeName]['ctrlProps'])) {
|
||||
foreach ($unparsedLoadedData['sheets'][$sheetCodeName]['ctrlProps'] as $ctrlProp) {
|
||||
$zip->addFromString($ctrlProp['filePath'], $ctrlProp['content']);
|
||||
$zip->addFile($ctrlProp['filePath'], $ctrlProp['content']);
|
||||
}
|
||||
}
|
||||
if (isset($unparsedLoadedData['sheets'][$sheetCodeName]['printerSettings'])) {
|
||||
foreach ($unparsedLoadedData['sheets'][$sheetCodeName]['printerSettings'] as $ctrlProp) {
|
||||
$zip->addFromString($ctrlProp['filePath'], $ctrlProp['content']);
|
||||
$zip->addFile($ctrlProp['filePath'], $ctrlProp['content']);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -319,13 +309,13 @@ class Xlsx extends BaseWriter
|
|||
// Add drawing and image relationship parts
|
||||
if (($drawingCount > 0) || ($chartCount > 0)) {
|
||||
// Drawing relationships
|
||||
$zip->addFromString('xl/drawings/_rels/drawing' . ($i + 1) . '.xml.rels', $this->getWriterPart('Rels')->writeDrawingRelationships($this->spreadSheet->getSheet($i), $chartRef1, $this->includeCharts));
|
||||
$zip->addFile('xl/drawings/_rels/drawing' . ($i + 1) . '.xml.rels', $this->getWriterPart('Rels')->writeDrawingRelationships($this->spreadSheet->getSheet($i), $chartRef1, $this->includeCharts));
|
||||
|
||||
// Drawings
|
||||
$zip->addFromString('xl/drawings/drawing' . ($i + 1) . '.xml', $this->getWriterPart('Drawing')->writeDrawings($this->spreadSheet->getSheet($i), $this->includeCharts));
|
||||
$zip->addFile('xl/drawings/drawing' . ($i + 1) . '.xml', $this->getWriterPart('Drawing')->writeDrawings($this->spreadSheet->getSheet($i), $this->includeCharts));
|
||||
} elseif (isset($unparsedLoadedData['sheets'][$sheetCodeName]['drawingAlternateContents'])) {
|
||||
// Drawings
|
||||
$zip->addFromString('xl/drawings/drawing' . ($i + 1) . '.xml', $this->getWriterPart('Drawing')->writeDrawings($this->spreadSheet->getSheet($i), $this->includeCharts));
|
||||
$zip->addFile('xl/drawings/drawing' . ($i + 1) . '.xml', $this->getWriterPart('Drawing')->writeDrawings($this->spreadSheet->getSheet($i), $this->includeCharts));
|
||||
}
|
||||
|
||||
// Add unparsed drawings
|
||||
|
@ -334,7 +324,7 @@ class Xlsx extends BaseWriter
|
|||
$drawingFile = array_search($relId, $unparsedLoadedData['sheets'][$sheetCodeName]['drawingOriginalIds']);
|
||||
if ($drawingFile !== false) {
|
||||
$drawingFile = ltrim($drawingFile, '.');
|
||||
$zip->addFromString('xl' . $drawingFile, $drawingXml);
|
||||
$zip->addFile('xl' . $drawingFile, $drawingXml);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -342,30 +332,30 @@ class Xlsx extends BaseWriter
|
|||
// Add comment relationship parts
|
||||
if (count($this->spreadSheet->getSheet($i)->getComments()) > 0) {
|
||||
// VML Comments
|
||||
$zip->addFromString('xl/drawings/vmlDrawing' . ($i + 1) . '.vml', $this->getWriterPart('Comments')->writeVMLComments($this->spreadSheet->getSheet($i)));
|
||||
$zip->addFile('xl/drawings/vmlDrawing' . ($i + 1) . '.vml', $this->getWriterPart('Comments')->writeVMLComments($this->spreadSheet->getSheet($i)));
|
||||
|
||||
// Comments
|
||||
$zip->addFromString('xl/comments' . ($i + 1) . '.xml', $this->getWriterPart('Comments')->writeComments($this->spreadSheet->getSheet($i)));
|
||||
$zip->addFile('xl/comments' . ($i + 1) . '.xml', $this->getWriterPart('Comments')->writeComments($this->spreadSheet->getSheet($i)));
|
||||
}
|
||||
|
||||
// Add unparsed relationship parts
|
||||
if (isset($unparsedLoadedData['sheets'][$sheetCodeName]['vmlDrawings'])) {
|
||||
foreach ($unparsedLoadedData['sheets'][$sheetCodeName]['vmlDrawings'] as $vmlDrawing) {
|
||||
$zip->addFromString($vmlDrawing['filePath'], $vmlDrawing['content']);
|
||||
$zip->addFile($vmlDrawing['filePath'], $vmlDrawing['content']);
|
||||
}
|
||||
}
|
||||
|
||||
// Add header/footer relationship parts
|
||||
if (count($this->spreadSheet->getSheet($i)->getHeaderFooter()->getImages()) > 0) {
|
||||
// VML Drawings
|
||||
$zip->addFromString('xl/drawings/vmlDrawingHF' . ($i + 1) . '.vml', $this->getWriterPart('Drawing')->writeVMLHeaderFooterImages($this->spreadSheet->getSheet($i)));
|
||||
$zip->addFile('xl/drawings/vmlDrawingHF' . ($i + 1) . '.vml', $this->getWriterPart('Drawing')->writeVMLHeaderFooterImages($this->spreadSheet->getSheet($i)));
|
||||
|
||||
// VML Drawing relationships
|
||||
$zip->addFromString('xl/drawings/_rels/vmlDrawingHF' . ($i + 1) . '.vml.rels', $this->getWriterPart('Rels')->writeHeaderFooterDrawingRelationships($this->spreadSheet->getSheet($i)));
|
||||
$zip->addFile('xl/drawings/_rels/vmlDrawingHF' . ($i + 1) . '.vml.rels', $this->getWriterPart('Rels')->writeHeaderFooterDrawingRelationships($this->spreadSheet->getSheet($i)));
|
||||
|
||||
// Media
|
||||
foreach ($this->spreadSheet->getSheet($i)->getHeaderFooter()->getImages() as $image) {
|
||||
$zip->addFromString('xl/media/' . $image->getIndexedFilename(), file_get_contents($image->getPath()));
|
||||
$zip->addFile('xl/media/' . $image->getIndexedFilename(), file_get_contents($image->getPath()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -388,7 +378,7 @@ class Xlsx extends BaseWriter
|
|||
$imageContents = file_get_contents($imagePath);
|
||||
}
|
||||
|
||||
$zip->addFromString('xl/media/' . str_replace(' ', '_', $this->getDrawingHashTable()->getByIndex($i)->getIndexedFilename()), $imageContents);
|
||||
$zip->addFile('xl/media/' . str_replace(' ', '_', $this->getDrawingHashTable()->getByIndex($i)->getIndexedFilename()), $imageContents);
|
||||
} elseif ($this->getDrawingHashTable()->getByIndex($i) instanceof MemoryDrawing) {
|
||||
ob_start();
|
||||
call_user_func(
|
||||
|
@ -398,7 +388,7 @@ class Xlsx extends BaseWriter
|
|||
$imageContents = ob_get_contents();
|
||||
ob_end_clean();
|
||||
|
||||
$zip->addFromString('xl/media/' . str_replace(' ', '_', $this->getDrawingHashTable()->getByIndex($i)->getIndexedFilename()), $imageContents);
|
||||
$zip->addFile('xl/media/' . str_replace(' ', '_', $this->getDrawingHashTable()->getByIndex($i)->getIndexedFilename()), $imageContents);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -406,17 +396,13 @@ class Xlsx extends BaseWriter
|
|||
Calculation::getInstance($this->spreadSheet)->getDebugLog()->setWriteDebugLog($saveDebugLog);
|
||||
|
||||
// Close file
|
||||
if ($zip->close() === false) {
|
||||
throw new WriterException("Could not close zip file $pFilename.");
|
||||
try {
|
||||
$zip->finish();
|
||||
} catch (OverflowException $e) {
|
||||
throw new WriterException('Could not close resource.');
|
||||
}
|
||||
|
||||
// If a temporary file was used, copy it to the correct file stream
|
||||
if ($originalFilename != $pFilename) {
|
||||
if (copy($pFilename, $originalFilename) === false) {
|
||||
throw new WriterException("Could not copy temporary zip file $pFilename to $originalFilename.");
|
||||
}
|
||||
@unlink($pFilename);
|
||||
}
|
||||
$this->maybeCloseFileHandle();
|
||||
} else {
|
||||
throw new WriterException('PhpSpreadsheet object unassigned.');
|
||||
}
|
||||
|
|
|
@ -0,0 +1,45 @@
|
|||
<?php
|
||||
|
||||
namespace PhpOffice\PhpSpreadsheetTests\Functional;
|
||||
|
||||
use PhpOffice\PhpSpreadsheet\IOFactory;
|
||||
use PhpOffice\PhpSpreadsheet\Spreadsheet;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class StreamTest extends TestCase
|
||||
{
|
||||
public function providerFormats(): array
|
||||
{
|
||||
return [
|
||||
['Xls'],
|
||||
['Xlsx'],
|
||||
['Ods'],
|
||||
['Csv'],
|
||||
['Html'],
|
||||
['Tcpdf'],
|
||||
['Dompdf'],
|
||||
['Mpdf'],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider providerFormats
|
||||
*
|
||||
* @param string $format
|
||||
*/
|
||||
public function testAllWritersCanWriteToStream(string $format): void
|
||||
{
|
||||
$spreadsheet = new Spreadsheet();
|
||||
$spreadsheet->getActiveSheet()->setCellValue('A1', 'foo');
|
||||
$writer = IOFactory::createWriter($spreadsheet, $format);
|
||||
|
||||
$stream = fopen('php://memory', 'wb+');
|
||||
self::assertSame(0, fstat($stream)['size']);
|
||||
|
||||
$writer->save($stream);
|
||||
|
||||
self::assertIsResource($stream, 'should not close the stream for further usage out of PhpSpreadsheet');
|
||||
self::assertGreaterThan(0, fstat($stream)['size'], 'something should have been written to the stream');
|
||||
self::assertGreaterThan(0, ftell($stream), 'should not be rewinded, because not all streams support it');
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue