Test Failed
Push — develop ( 90366f...812a46 )
by Adrien
28:16
created

StringTable::createStringTable()   C

Complexity

Conditions 14
Paths 8

Size

Total Lines 35
Code Lines 22

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 23
CRAP Score 14

Importance

Changes 0
Metric Value
cc 14
eloc 22
nc 8
nop 2
dl 0
loc 35
ccs 23
cts 23
cp 1
crap 14
rs 5.0864
c 0
b 0
f 0

How to fix   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\DataType;
6
use PhpOffice\PhpSpreadsheet\RichText\RichText;
7
use PhpOffice\PhpSpreadsheet\RichText\Run;
8
use PhpOffice\PhpSpreadsheet\Shared\StringHelper;
9
use PhpOffice\PhpSpreadsheet\Shared\XMLWriter;
10
use PhpOffice\PhpSpreadsheet\Worksheet\Worksheet;
0 ignored issues
show
Bug introduced by
This use statement conflicts with another class in this namespace, PhpOffice\PhpSpreadsheet\Writer\Xlsx\Worksheet. Consider defining an alias.

Let?s assume that you have a directory layout like this:

.
|-- OtherDir
|   |-- Bar.php
|   `-- Foo.php
`-- SomeDir
    `-- Foo.php

and let?s assume the following content of Bar.php:

// Bar.php
namespace OtherDir;

use SomeDir\Foo; // This now conflicts the class OtherDir\Foo

If both files OtherDir/Foo.php and SomeDir/Foo.php are loaded in the same runtime, you will see a PHP error such as the following:

PHP Fatal error:  Cannot use SomeDir\Foo as Foo because the name is already in use in OtherDir/Foo.php

However, as OtherDir/Foo.php does not necessarily have to be loaded and the error is only triggered if it is loaded before OtherDir/Bar.php, this problem might go unnoticed for a while. In order to prevent this error from surfacing, you must import the namespace with a different alias:

// Bar.php
namespace OtherDir;

use SomeDir\Foo as SomeDirFoo; // There is no conflict anymore.
Loading history...
11
use PhpOffice\PhpSpreadsheet\Writer\Exception as WriterException;
12
13
class StringTable extends WriterPart
14
{
15
    /**
16
     * Create worksheet stringtable.
17
     *
18
     * @param Worksheet $pSheet Worksheet
19
     * @param string[] $pExistingTable Existing table to eventually merge with
20
     *
21
     * @throws WriterException
22
     *
23
     * @return string[] String table for worksheet
24
     */
25 56
    public function createStringTable(Worksheet $pSheet, $pExistingTable = null)
26
    {
27
        // Create string lookup table
28 56
        $aStringTable = [];
29 56
        $cellCollection = null;
0 ignored issues
show
Unused Code introduced by
The assignment to $cellCollection is dead and can be removed.
Loading history...
30 56
        $aFlippedStringTable = null; // For faster lookup
0 ignored issues
show
Unused Code introduced by
The assignment to $aFlippedStringTable is dead and can be removed.
Loading history...
31
32
        // Is an existing table given?
33 56
        if (($pExistingTable !== null) && is_array($pExistingTable)) {
34 56
            $aStringTable = $pExistingTable;
35
        }
36
37
        // Fill index array
38 56
        $aFlippedStringTable = $this->flipStringTable($aStringTable);
39
40
        // Loop through cells
41 56
        foreach ($pSheet->getCoordinates() as $coordinate) {
42 56
            $cell = $pSheet->getCell($coordinate);
43 56
            $cellValue = $cell->getValue();
44 56
            if (!is_object($cellValue) &&
45 56
                ($cellValue !== null) &&
46 56
                $cellValue !== '' &&
47 56
                !isset($aFlippedStringTable[$cellValue]) &&
48 56
                ($cell->getDataType() == DataType::TYPE_STRING || $cell->getDataType() == DataType::TYPE_STRING2 || $cell->getDataType() == DataType::TYPE_NULL)) {
49 50
                $aStringTable[] = $cellValue;
50 50
                $aFlippedStringTable[$cellValue] = true;
51 53
            } elseif ($cellValue instanceof RichText &&
52 53
                ($cellValue !== null) &&
53 53
                !isset($aFlippedStringTable[$cellValue->getHashCode()])) {
54 10
                $aStringTable[] = $cellValue;
55 56
                $aFlippedStringTable[$cellValue->getHashCode()] = true;
56
            }
57
        }
58
59 56
        return $aStringTable;
60
    }
61
62
    /**
63
     * Write string table to XML format.
64
     *
65
     * @param string[] $pStringTable
66
     *
67
     * @throws WriterException
68
     *
69
     * @return string XML Output
70
     */
71 56
    public function writeStringTable(array $pStringTable)
72
    {
73
        // Create XML writer
74 56
        $objWriter = null;
75 56 View Code Duplication
        if ($this->getParentWriter()->getUseDiskCaching()) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
76
            $objWriter = new XMLWriter(XMLWriter::STORAGE_DISK, $this->getParentWriter()->getDiskCachingDirectory());
77
        } else {
78 56
            $objWriter = new XMLWriter(XMLWriter::STORAGE_MEMORY);
79
        }
80
81
        // XML header
82 56
        $objWriter->startDocument('1.0', 'UTF-8', 'yes');
83
84
        // String table
85 56
        $objWriter->startElement('sst');
86 56
        $objWriter->writeAttribute('xmlns', 'http://schemas.openxmlformats.org/spreadsheetml/2006/main');
87 56
        $objWriter->writeAttribute('uniqueCount', count($pStringTable));
88
89
        // Loop through string table
90 56
        foreach ($pStringTable as $textElement) {
91 51
            $objWriter->startElement('si');
92
93 51
            if (!$textElement instanceof RichText) {
94 50
                $textToWrite = StringHelper::controlCharacterPHP2OOXML($textElement);
95 50
                $objWriter->startElement('t');
96 50
                if ($textToWrite !== trim($textToWrite)) {
97 2
                    $objWriter->writeAttribute('xml:space', 'preserve');
98
                }
99 50
                $objWriter->writeRawData($textToWrite);
100 50
                $objWriter->endElement();
101 10
            } elseif ($textElement instanceof RichText) {
102 10
                $this->writeRichText($objWriter, $textElement);
103
            }
104
105 51
            $objWriter->endElement();
106
        }
107
108 56
        $objWriter->endElement();
109
110 56
        return $objWriter->getData();
0 ignored issues
show
Bug Best Practice introduced by
The expression return $objWriter->getData() could also return false which is incompatible with the documented return type string. Did you maybe forget to handle an error condition?

If the returned type also contains false, it is an indicator that maybe an error condition leading to the specific return statement remains unhandled.

Loading history...
111
    }
112
113
    /**
114
     * Write Rich Text.
115
     *
116
     * @param XMLWriter $objWriter XML Writer
117
     * @param RichText $pRichText Rich text
118
     * @param string $prefix Optional Namespace prefix
119
     *
120
     * @throws WriterException
121
     */
122 13
    public function writeRichText(XMLWriter $objWriter, RichText $pRichText, $prefix = null)
123
    {
124 13
        if ($prefix !== null) {
125
            $prefix .= ':';
126
        }
127
128
        // Loop through rich text elements
129 13
        $elements = $pRichText->getRichTextElements();
130 13
        foreach ($elements as $element) {
131
            // r
132 13
            $objWriter->startElement($prefix . 'r');
133
134
            // rPr
135 13
            if ($element instanceof Run) {
136
                // rPr
137 10
                $objWriter->startElement($prefix . 'rPr');
138
139
                // rFont
140 10
                $objWriter->startElement($prefix . 'rFont');
141 10
                $objWriter->writeAttribute('val', $element->getFont()->getName());
142 10
                $objWriter->endElement();
143
144
                // Bold
145 10
                $objWriter->startElement($prefix . 'b');
146 10
                $objWriter->writeAttribute('val', ($element->getFont()->getBold() ? 'true' : 'false'));
147 10
                $objWriter->endElement();
148
149
                // Italic
150 10
                $objWriter->startElement($prefix . 'i');
151 10
                $objWriter->writeAttribute('val', ($element->getFont()->getItalic() ? 'true' : 'false'));
152 10
                $objWriter->endElement();
153
154
                // Superscript / subscript
155 10
                if ($element->getFont()->getSuperscript() || $element->getFont()->getSubscript()) {
156 1
                    $objWriter->startElement($prefix . 'vertAlign');
157 1
                    if ($element->getFont()->getSuperscript()) {
158 1
                        $objWriter->writeAttribute('val', 'superscript');
159 1
                    } elseif ($element->getFont()->getSubscript()) {
160 1
                        $objWriter->writeAttribute('val', 'subscript');
161
                    }
162 1
                    $objWriter->endElement();
163
                }
164
165
                // Strikethrough
166 10
                $objWriter->startElement($prefix . 'strike');
167 10
                $objWriter->writeAttribute('val', ($element->getFont()->getStrikethrough() ? 'true' : 'false'));
168 10
                $objWriter->endElement();
169
170
                // Color
171 10
                $objWriter->startElement($prefix . 'color');
172 10
                $objWriter->writeAttribute('rgb', $element->getFont()->getColor()->getARGB());
173 10
                $objWriter->endElement();
174
175
                // Size
176 10
                $objWriter->startElement($prefix . 'sz');
177 10
                $objWriter->writeAttribute('val', $element->getFont()->getSize());
178 10
                $objWriter->endElement();
179
180
                // Underline
181 10
                $objWriter->startElement($prefix . 'u');
182 10
                $objWriter->writeAttribute('val', $element->getFont()->getUnderline());
183 10
                $objWriter->endElement();
184
185 10
                $objWriter->endElement();
186
            }
187
188
            // t
189 13
            $objWriter->startElement($prefix . 't');
190 13
            $objWriter->writeAttribute('xml:space', 'preserve');
191 13
            $objWriter->writeRawData(StringHelper::controlCharacterPHP2OOXML($element->getText()));
192 13
            $objWriter->endElement();
193
194 13
            $objWriter->endElement();
195
        }
196 13
    }
197
198
    /**
199
     * Write Rich Text.
200
     *
201
     * @param XMLWriter $objWriter XML Writer
202
     * @param RichText|string $pRichText text string or Rich text
203
     * @param string $prefix Optional Namespace prefix
204
     *
205
     * @throws WriterException
206
     */
207 13
    public function writeRichTextForCharts(XMLWriter $objWriter, $pRichText = null, $prefix = null)
208
    {
209 13
        if (!$pRichText instanceof RichText) {
210 12
            $textRun = $pRichText;
211 12
            $pRichText = new RichText();
212 12
            $pRichText->createTextRun($textRun);
213
        }
214
215 13
        if ($prefix !== null) {
216 13
            $prefix .= ':';
217
        }
218
219
        // Loop through rich text elements
220 13
        $elements = $pRichText->getRichTextElements();
221 13
        foreach ($elements as $element) {
222
            // r
223 13
            $objWriter->startElement($prefix . 'r');
224
225
            // rPr
226 13
            $objWriter->startElement($prefix . 'rPr');
227
228
            // Bold
229 13
            $objWriter->writeAttribute('b', ($element->getFont()->getBold() ? 1 : 0));
230
            // Italic
231 13
            $objWriter->writeAttribute('i', ($element->getFont()->getItalic() ? 1 : 0));
232
            // Underline
233 13
            $underlineType = $element->getFont()->getUnderline();
234
            switch ($underlineType) {
235 13
                case 'single':
236 1
                    $underlineType = 'sng';
237
238 1
                    break;
239 13
                case 'double':
240 1
                    $underlineType = 'dbl';
241
242 1
                    break;
243
            }
244 13
            $objWriter->writeAttribute('u', $underlineType);
245
            // Strikethrough
246 13
            $objWriter->writeAttribute('strike', ($element->getFont()->getStrikethrough() ? 'sngStrike' : 'noStrike'));
247
248
            // rFont
249 13
            $objWriter->startElement($prefix . 'latin');
250 13
            $objWriter->writeAttribute('typeface', $element->getFont()->getName());
251 13
            $objWriter->endElement();
252
253 13
            $objWriter->endElement();
254
255
            // t
256 13
            $objWriter->startElement($prefix . 't');
257 13
            $objWriter->writeRawData(StringHelper::controlCharacterPHP2OOXML($element->getText()));
258 13
            $objWriter->endElement();
259
260 13
            $objWriter->endElement();
261
        }
262 13
    }
263
264
    /**
265
     * Flip string table (for index searching).
266
     *
267
     * @param array $stringTable Stringtable
268
     *
269
     * @return array
270
     */
271 56
    public function flipStringTable(array $stringTable)
272
    {
273
        // Return value
274 56
        $returnValue = [];
275
276
        // Loop through stringtable and add flipped items to $returnValue
277 56
        foreach ($stringTable as $key => $value) {
278 51
            if (!$value instanceof RichText) {
279 50
                $returnValue[$value] = $key;
280 10
            } elseif ($value instanceof RichText) {
281 51
                $returnValue[$value->getHashCode()] = $key;
282
            }
283
        }
284
285 56
        return $returnValue;
286
    }
287
}
288