108 lines
3.9 KiB
PHP
108 lines
3.9 KiB
PHP
<?php
|
|
|
|
namespace Box\Spout\Writer\XLSX\Helper;
|
|
|
|
use Box\Spout\Common\Exception\IOException;
|
|
|
|
/**
|
|
* Class SharedStringsHelper
|
|
* This class provides helper functions to write shared strings
|
|
*
|
|
* @package Box\Spout\Writer\XLSX\Helper
|
|
*/
|
|
class SharedStringsHelper
|
|
{
|
|
const SHARED_STRINGS_FILE_NAME = 'sharedStrings.xml';
|
|
|
|
const SHARED_STRINGS_XML_FILE_FIRST_PART_HEADER = <<<EOD
|
|
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
|
<sst xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main"
|
|
EOD;
|
|
|
|
/**
|
|
* This number must be really big so that the no generated file will have more strings than that.
|
|
* If the strings number goes above, characters will be overwritten in an unwanted way and will corrupt the file.
|
|
*/
|
|
const DEFAULT_STRINGS_COUNT_PART = 'count="9999999999999" uniqueCount="9999999999999"';
|
|
|
|
/** @var resource Pointer to the sharedStrings.xml file */
|
|
protected $sharedStringsFilePointer;
|
|
|
|
/** @var int Number of shared strings already written */
|
|
protected $numSharedStrings = 0;
|
|
|
|
/** @var \Box\Spout\Common\Escaper\XLSX Strings escaper */
|
|
protected $stringsEscaper;
|
|
|
|
/**
|
|
* @param string $xlFolder Path to the "xl" folder
|
|
*/
|
|
public function __construct($xlFolder)
|
|
{
|
|
$sharedStringsFilePath = $xlFolder . '/' . self::SHARED_STRINGS_FILE_NAME;
|
|
$this->sharedStringsFilePointer = fopen($sharedStringsFilePath, 'w');
|
|
|
|
$this->throwIfSharedStringsFilePointerIsNotAvailable();
|
|
|
|
// the headers is split into different parts so that we can fseek and put in the correct count and uniqueCount later
|
|
$header = self::SHARED_STRINGS_XML_FILE_FIRST_PART_HEADER . ' ' . self::DEFAULT_STRINGS_COUNT_PART . '>';
|
|
fwrite($this->sharedStringsFilePointer, $header);
|
|
|
|
/** @noinspection PhpUnnecessaryFullyQualifiedNameInspection */
|
|
$this->stringsEscaper = \Box\Spout\Common\Escaper\XLSX::getInstance();
|
|
}
|
|
|
|
/**
|
|
* Checks if the book has been created. Throws an exception if not created yet.
|
|
*
|
|
* @return void
|
|
* @throws \Box\Spout\Common\Exception\IOException If the sheet data file cannot be opened for writing
|
|
*/
|
|
protected function throwIfSharedStringsFilePointerIsNotAvailable()
|
|
{
|
|
if (!$this->sharedStringsFilePointer) {
|
|
throw new IOException('Unable to open shared strings file for writing.');
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Writes the given string into the sharedStrings.xml file.
|
|
* Starting and ending whitespaces are preserved.
|
|
*
|
|
* @param string $string
|
|
* @return int ID of the written shared string
|
|
*/
|
|
public function writeString($string)
|
|
{
|
|
fwrite($this->sharedStringsFilePointer, '<si><t xml:space="preserve">' . $this->stringsEscaper->escape($string) . '</t></si>');
|
|
$this->numSharedStrings++;
|
|
|
|
// Shared string ID is zero-based
|
|
return ($this->numSharedStrings - 1);
|
|
}
|
|
|
|
/**
|
|
* Finishes writing the data in the sharedStrings.xml file and closes the file.
|
|
*
|
|
* @return void
|
|
*/
|
|
public function close()
|
|
{
|
|
if (!is_resource($this->sharedStringsFilePointer)) {
|
|
return;
|
|
}
|
|
|
|
fwrite($this->sharedStringsFilePointer, '</sst>');
|
|
|
|
// Replace the default strings count with the actual number of shared strings in the file header
|
|
$firstPartHeaderLength = strlen(self::SHARED_STRINGS_XML_FILE_FIRST_PART_HEADER);
|
|
$defaultStringsCountPartLength = strlen(self::DEFAULT_STRINGS_COUNT_PART);
|
|
|
|
// Adding 1 to take into account the space between the last xml attribute and "count"
|
|
fseek($this->sharedStringsFilePointer, $firstPartHeaderLength + 1);
|
|
fwrite($this->sharedStringsFilePointer, sprintf("%-{$defaultStringsCountPartLength}s", 'count="' . $this->numSharedStrings . '" uniqueCount="' . $this->numSharedStrings . '"'));
|
|
|
|
fclose($this->sharedStringsFilePointer);
|
|
}
|
|
}
|