File: /home/retile.ru/public_html/system/library/Spout/Writer/XLSX/Helper/SharedStringsHelper.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);
    }
}