Proyectos de Subversion Moodle

Rev

| Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
1 efrain 1
<?php
2
 
3
declare(strict_types=1);
4
 
5
namespace OpenSpout\Writer\XLSX\Manager;
6
 
7
use OpenSpout\Common\Helper\Escaper;
8
 
9
/**
10
 * @internal
11
 */
12
final class SharedStringsManager
13
{
14
    public const SHARED_STRINGS_FILE_NAME = 'sharedStrings.xml';
15
 
16
    public const SHARED_STRINGS_XML_FILE_FIRST_PART_HEADER = <<<'EOD'
17
        <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
18
        <sst xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main"
19
        EOD;
20
 
21
    /**
22
     * This number must be really big so that the no generated file will have more strings than that.
23
     * If the strings number goes above, characters will be overwritten in an unwanted way and will corrupt the file.
24
     */
25
    public const DEFAULT_STRINGS_COUNT_PART = 'count="9999999999999" uniqueCount="9999999999999"';
26
 
27
    /** @var resource Pointer to the sharedStrings.xml file */
28
    private $sharedStringsFilePointer;
29
 
30
    /** @var int Number of shared strings already written */
31
    private int $numSharedStrings = 0;
32
 
33
    /** @var Escaper\XLSX Strings escaper */
34
    private readonly Escaper\XLSX $stringsEscaper;
35
 
36
    /**
37
     * @param string       $xlFolder       Path to the "xl" folder
38
     * @param Escaper\XLSX $stringsEscaper Strings escaper
39
     */
40
    public function __construct(string $xlFolder, Escaper\XLSX $stringsEscaper)
41
    {
42
        $sharedStringsFilePath = $xlFolder.\DIRECTORY_SEPARATOR.self::SHARED_STRINGS_FILE_NAME;
43
        $resource = fopen($sharedStringsFilePath, 'w');
44
        \assert(false !== $resource);
45
        $this->sharedStringsFilePointer = $resource;
46
 
47
        // the headers is split into different parts so that we can fseek and put in the correct count and uniqueCount later
48
        $header = self::SHARED_STRINGS_XML_FILE_FIRST_PART_HEADER.' '.self::DEFAULT_STRINGS_COUNT_PART.'>';
49
        fwrite($this->sharedStringsFilePointer, $header);
50
 
51
        $this->stringsEscaper = $stringsEscaper;
52
    }
53
 
54
    /**
55
     * Writes the given string into the sharedStrings.xml file.
56
     * Starting and ending whitespaces are preserved.
57
     *
58
     * @return int ID of the written shared string
59
     */
60
    public function writeString(string $string): int
61
    {
62
        fwrite($this->sharedStringsFilePointer, '<si><t xml:space="preserve">'.$this->stringsEscaper->escape($string).'</t></si>');
63
        ++$this->numSharedStrings;
64
 
65
        // Shared string ID is zero-based
66
        return $this->numSharedStrings - 1;
67
    }
68
 
69
    /**
70
     * Finishes writing the data in the sharedStrings.xml file and closes the file.
71
     */
72
    public function close(): void
73
    {
74
        fwrite($this->sharedStringsFilePointer, '</sst>');
75
 
76
        // Replace the default strings count with the actual number of shared strings in the file header
77
        $firstPartHeaderLength = \strlen(self::SHARED_STRINGS_XML_FILE_FIRST_PART_HEADER);
78
        $defaultStringsCountPartLength = \strlen(self::DEFAULT_STRINGS_COUNT_PART);
79
 
80
        // Adding 1 to take into account the space between the last xml attribute and "count"
81
        fseek($this->sharedStringsFilePointer, $firstPartHeaderLength + 1);
82
        fwrite($this->sharedStringsFilePointer, sprintf("%-{$defaultStringsCountPartLength}s", 'count="'.$this->numSharedStrings.'" uniqueCount="'.$this->numSharedStrings.'"'));
83
 
84
        fclose($this->sharedStringsFilePointer);
85
    }
86
}