Passed
Push — master ( b504ba...c2a964 )
by
unknown
21:09 queued 09:01
created

StringTable::writeRichText()   C

Complexity

Conditions 16
Paths 132

Size

Total Lines 81
Code Lines 45

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 45
CRAP Score 16.0026

Importance

Changes 0
Metric Value
eloc 45
c 0
b 0
f 0
dl 0
loc 81
ccs 45
cts 46
cp 0.9783
rs 5.3
cc 16
nc 132
nop 3
crap 16.0026

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
namespace PhpOffice\PhpSpreadsheet\Writer\Xlsx;
4
5
use PhpOffice\PhpSpreadsheet\Cell\Cell;
6
use PhpOffice\PhpSpreadsheet\Cell\DataType;
7
use PhpOffice\PhpSpreadsheet\Chart\ChartColor;
8
use PhpOffice\PhpSpreadsheet\Reader\Xlsx\Namespaces;
9
use PhpOffice\PhpSpreadsheet\RichText\RichText;
10
use PhpOffice\PhpSpreadsheet\RichText\Run;
11
use PhpOffice\PhpSpreadsheet\Shared\StringHelper;
12
use PhpOffice\PhpSpreadsheet\Shared\XMLWriter;
13
use PhpOffice\PhpSpreadsheet\Worksheet\Worksheet as ActualWorksheet;
14
15
class StringTable extends WriterPart
16
{
17
    /**
18
     * Create worksheet stringtable.
19
     *
20
     * @param string[] $existingTable Existing table to eventually merge with
21
     *
22
     * @return string[] String table for worksheet
23
     */
24 375
    public function createStringTable(ActualWorksheet $worksheet, ?array $existingTable = null): array
25
    {
26
        // Create string lookup table
27
        /** @var string[] */
28 375
        $aStringTable = $existingTable ?? [];
29
30
        // Fill index array
31 375
        $aFlippedStringTable = $this->flipStringTable($aStringTable);
32
33
        // Loop through cells
34 375
        foreach ($worksheet->getCellCollection()->getCoordinates() as $coordinate) {
35
            /** @var Cell $cell */
36 355
            $cell = $worksheet->getCellCollection()->get($coordinate);
37 355
            $cellValue = $cell->getValue();
38
            if (
39 355
                !is_object($cellValue)
40 355
                && ($cellValue !== null)
41 355
                && $cellValue !== ''
42 355
                && ($cell->getDataType() == DataType::TYPE_STRING || $cell->getDataType() == DataType::TYPE_STRING2 || $cell->getDataType() == DataType::TYPE_NULL)
43 355
                && !isset($aFlippedStringTable[$cellValue])
44
            ) {
45 234
                $aStringTable[] = $cellValue;
46 234
                $aFlippedStringTable[$cellValue] = true;
47
            } elseif (
48 313
                $cellValue instanceof RichText
49 313
                && !isset($aFlippedStringTable[$cellValue->getHashCode()])
50
            ) {
51 19
                $aStringTable[] = $cellValue;
52 19
                $aFlippedStringTable[$cellValue->getHashCode()] = true;
53
            }
54
        }
55
        /** @var string[] $aStringTable */
56
57 375
        return $aStringTable;
58
    }
59
60
    /**
61
     * Write string table to XML format.
62
     *
63
     * @param (RichText|string)[] $stringTable
64
     *
65
     * @return string XML Output
66
     */
67 375
    public function writeStringTable(array $stringTable): string
68
    {
69
        // Create XML writer
70 375
        $objWriter = null;
71 375
        if ($this->getParentWriter()->getUseDiskCaching()) {
72
            $objWriter = new XMLWriter(XMLWriter::STORAGE_DISK, $this->getParentWriter()->getDiskCachingDirectory());
73
        } else {
74 375
            $objWriter = new XMLWriter(XMLWriter::STORAGE_MEMORY);
75
        }
76
77
        // XML header
78 375
        $objWriter->startDocument('1.0', 'UTF-8', 'yes');
79
80
        // String table
81 375
        $objWriter->startElement('sst');
82 375
        $objWriter->writeAttribute('xmlns', Namespaces::MAIN);
83 375
        $objWriter->writeAttribute('uniqueCount', (string) count($stringTable));
84
85
        // Loop through string table
86 375
        foreach ($stringTable as $textElement) {
87 237
            $objWriter->startElement('si');
88
89 237
            if (!($textElement instanceof RichText)) {
90 234
                $textToWrite = StringHelper::controlCharacterPHP2OOXML($textElement);
91 234
                $objWriter->startElement('t');
92 234
                if ($textToWrite !== trim($textToWrite)) {
93 8
                    $objWriter->writeAttribute('xml:space', 'preserve');
94
                }
95 234
                $objWriter->writeRawData($textToWrite);
96 234
                $objWriter->endElement();
97
            } else {
98 19
                $this->writeRichText($objWriter, $textElement);
99
            }
100
101 237
            $objWriter->endElement();
102
        }
103
104 375
        $objWriter->endElement();
105
106 375
        return $objWriter->getData();
107
    }
108
109
    /**
110
     * Write Rich Text.
111
     *
112
     * @param ?string $prefix Optional Namespace prefix
113
     */
114 36
    public function writeRichText(XMLWriter $objWriter, RichText $richText, ?string $prefix = null): void
115
    {
116 36
        if ($prefix !== null) {
117
            $prefix .= ':';
118
        }
119
120
        // Loop through rich text elements
121 36
        $elements = $richText->getRichTextElements();
122 36
        foreach ($elements as $element) {
123
            // r
124 33
            $objWriter->startElement($prefix . 'r');
125
126
            // rPr
127 33
            if ($element instanceof Run && $element->getFont() !== null) {
128
                // rPr
129 21
                $objWriter->startElement($prefix . 'rPr');
130
131
                // rFont
132 21
                if ($element->getFont()->getName() !== null) {
133 21
                    $objWriter->startElement($prefix . 'rFont');
134 21
                    $objWriter->writeAttribute('val', $element->getFont()->getName());
135 21
                    $objWriter->endElement();
136
                }
137
138
                // Bold
139 21
                $objWriter->startElement($prefix . 'b');
140 21
                $objWriter->writeAttribute('val', ($element->getFont()->getBold() ? 'true' : 'false'));
141 21
                $objWriter->endElement();
142
143
                // Italic
144 21
                $objWriter->startElement($prefix . 'i');
145 21
                $objWriter->writeAttribute('val', ($element->getFont()->getItalic() ? 'true' : 'false'));
146 21
                $objWriter->endElement();
147
148
                // Superscript / subscript
149 21
                if ($element->getFont()->getSuperscript() || $element->getFont()->getSubscript()) {
150 1
                    $objWriter->startElement($prefix . 'vertAlign');
151 1
                    if ($element->getFont()->getSuperscript()) {
152 1
                        $objWriter->writeAttribute('val', 'superscript');
153 1
                    } elseif ($element->getFont()->getSubscript()) {
154 1
                        $objWriter->writeAttribute('val', 'subscript');
155
                    }
156 1
                    $objWriter->endElement();
157
                }
158
159
                // Strikethrough
160 21
                $objWriter->startElement($prefix . 'strike');
161 21
                $objWriter->writeAttribute('val', ($element->getFont()->getStrikethrough() ? 'true' : 'false'));
162 21
                $objWriter->endElement();
163
164
                // Color
165 21
                if ($element->getFont()->getColor()->getARGB() !== null) {
166 21
                    $objWriter->startElement($prefix . 'color');
167 21
                    $objWriter->writeAttribute('rgb', $element->getFont()->getColor()->getARGB());
168 21
                    $objWriter->endElement();
169
                }
170
171
                // Size
172 21
                if ($element->getFont()->getSize() !== null) {
173 21
                    $objWriter->startElement($prefix . 'sz');
174 21
                    $objWriter->writeAttribute('val', (string) $element->getFont()->getSize());
175 21
                    $objWriter->endElement();
176
                }
177
178
                // Underline
179 21
                if ($element->getFont()->getUnderline() !== null) {
180 21
                    $objWriter->startElement($prefix . 'u');
181 21
                    $objWriter->writeAttribute('val', $element->getFont()->getUnderline());
182 21
                    $objWriter->endElement();
183
                }
184
185 21
                $objWriter->endElement();
186
            }
187
188
            // t
189 33
            $objWriter->startElement($prefix . 't');
190 33
            $objWriter->writeAttribute('xml:space', 'preserve');
191 33
            $objWriter->writeRawData(StringHelper::controlCharacterPHP2OOXML($element->getText()));
192 33
            $objWriter->endElement();
193
194 33
            $objWriter->endElement();
195
        }
196
    }
197
198
    /**
199
     * Write Rich Text.
200
     *
201
     * @param RichText|string $richText text string or Rich text
202
     * @param string $prefix Optional Namespace prefix
203
     */
204 83
    public function writeRichTextForCharts(XMLWriter $objWriter, $richText = null, string $prefix = ''): void
205
    {
206 83
        if (!($richText instanceof RichText)) {
207 50
            $textRun = $richText;
208 50
            $richText = new RichText();
209 50
            $run = $richText->createTextRun($textRun ?? '');
210 50
            $run->setFont(null);
211
        }
212
213 83
        if ($prefix !== '') {
214 83
            $prefix .= ':';
215
        }
216
217
        // Loop through rich text elements
218 83
        $elements = $richText->getRichTextElements();
219 83
        foreach ($elements as $element) {
220
            // r
221 83
            $objWriter->startElement($prefix . 'r');
222 83
            if ($element->getFont() !== null) {
223
                // rPr
224 28
                $objWriter->startElement($prefix . 'rPr');
225 28
                $fontSize = $element->getFont()->getSize();
226 28
                if (is_numeric($fontSize)) {
227 22
                    $fontSize *= (($fontSize < 100) ? 100 : 1);
228 22
                    $objWriter->writeAttribute('sz', (string) $fontSize);
229
                }
230
231
                // Bold
232 28
                $objWriter->writeAttribute('b', ($element->getFont()->getBold() ? '1' : '0'));
233
                // Italic
234 28
                $objWriter->writeAttribute('i', ($element->getFont()->getItalic() ? '1' : '0'));
235
                // Underline
236 28
                $underlineType = $element->getFont()->getUnderline();
237
                switch ($underlineType) {
238 28
                    case 'single':
239 6
                        $underlineType = 'sng';
240
241 6
                        break;
242 28
                    case 'double':
243 5
                        $underlineType = 'dbl';
244
245 5
                        break;
246
                }
247 28
                if ($underlineType !== null) {
248 28
                    $objWriter->writeAttribute('u', $underlineType);
249
                }
250
                // Strikethrough
251 28
                $objWriter->writeAttribute('strike', ($element->getFont()->getStriketype() ?: 'noStrike'));
252
                // Superscript/subscript
253 28
                if ($element->getFont()->getBaseLine()) {
254 5
                    $objWriter->writeAttribute('baseline', (string) $element->getFont()->getBaseLine());
255
                }
256
257
                // Color
258 28
                $this->writeChartTextColor($objWriter, $element->getFont()->getChartColor(), $prefix);
259
260
                // Underscore Color
261 28
                $this->writeChartTextColor($objWriter, $element->getFont()->getUnderlineColor(), $prefix, 'uFill');
262
263
                // fontName
264 28
                if ($element->getFont()->getLatin()) {
265 23
                    $objWriter->startElement($prefix . 'latin');
266 23
                    $objWriter->writeAttribute('typeface', $element->getFont()->getLatin());
267 23
                    $objWriter->endElement();
268
                }
269 28
                if ($element->getFont()->getEastAsian()) {
270 21
                    $objWriter->startElement($prefix . 'ea');
271 21
                    $objWriter->writeAttribute('typeface', $element->getFont()->getEastAsian());
272 21
                    $objWriter->endElement();
273
                }
274 28
                if ($element->getFont()->getComplexScript()) {
275 21
                    $objWriter->startElement($prefix . 'cs');
276 21
                    $objWriter->writeAttribute('typeface', $element->getFont()->getComplexScript());
277 21
                    $objWriter->endElement();
278
                }
279
280 28
                $objWriter->endElement();
281
            }
282
283
            // t
284 83
            $objWriter->startElement($prefix . 't');
285 83
            $objWriter->writeRawData(StringHelper::controlCharacterPHP2OOXML($element->getText()));
286 83
            $objWriter->endElement();
287
288 83
            $objWriter->endElement();
289
        }
290
    }
291
292 28
    private function writeChartTextColor(XMLWriter $objWriter, ?ChartColor $underlineColor, string $prefix, ?string $openTag = ''): void
293
    {
294 28
        if ($underlineColor !== null) {
295 22
            $type = $underlineColor->getType();
296 22
            $value = $underlineColor->getValue();
297 22
            if (!empty($type) && !empty($value)) {
298 17
                if ($openTag !== '') {
299 5
                    $objWriter->startElement($prefix . $openTag);
300
                }
301 17
                $objWriter->startElement($prefix . 'solidFill');
302 17
                $objWriter->startElement($prefix . $type);
303 17
                $objWriter->writeAttribute('val', $value);
304 17
                $alpha = $underlineColor->getAlpha();
305 17
                if (is_numeric($alpha)) {
306
                    $objWriter->startElement('a:alpha');
307
                    $objWriter->writeAttribute('val', ChartColor::alphaToXml((int) $alpha));
308
                    $objWriter->endElement();
309
                }
310 17
                $objWriter->endElement(); // srgbClr/schemeClr/prstClr
311 17
                $objWriter->endElement(); // solidFill
312 17
                if ($openTag !== '') {
313 5
                    $objWriter->endElement(); // uFill
314
                }
315
            }
316
        }
317
    }
318
319
    /**
320
     * Flip string table (for index searching).
321
     *
322
     * @param array<RichText|string> $stringTable Stringtable
323
     *
324
     * @return array<RichText|string>
325
     */
326 418
    public function flipStringTable(array $stringTable): array
327
    {
328
        // Return value
329 418
        $returnValue = [];
330
331
        // Loop through stringtable and add flipped items to $returnValue
332 418
        foreach ($stringTable as $key => $value) {
333 237
            if (!$value instanceof RichText) {
334 234
                $returnValue[$value] = $key;
335 19
            } elseif ($value instanceof RichText) {
336 19
                $returnValue[$value->getHashCode()] = $key;
337
            }
338
        }
339
340 418
        return $returnValue;
341
    }
342
}
343