Passed
Push — master ( dcb10e...d87ef3 )
by Adrien
12:23
created

Rels::writeWorkbookRelationships()   A

Complexity

Conditions 4
Paths 8

Size

Total Lines 66
Code Lines 36

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 18
CRAP Score 4.0023

Importance

Changes 0
Metric Value
eloc 36
dl 0
loc 66
ccs 18
cts 19
cp 0.9474
rs 9.344
c 0
b 0
f 0
cc 4
nc 8
nop 1
crap 4.0023

How to fix   Long Method   

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\Reader\Xlsx\Namespaces;
6
use PhpOffice\PhpSpreadsheet\Shared\XMLWriter;
7
use PhpOffice\PhpSpreadsheet\Spreadsheet;
8
use PhpOffice\PhpSpreadsheet\Worksheet\BaseDrawing;
9
use PhpOffice\PhpSpreadsheet\Worksheet\MemoryDrawing;
10
use PhpOffice\PhpSpreadsheet\Writer\Exception as WriterException;
11
12
class Rels extends WriterPart
13
{
14
    /**
15
     * Write relationships to XML format.
16
     *
17
     * @return string XML Output
18
     */
19 248
    public function writeRelationships(Spreadsheet $spreadsheet)
20
    {
21
        // Create XML writer
22 248
        $objWriter = null;
23 248
        if ($this->getParentWriter()->getUseDiskCaching()) {
24
            $objWriter = new XMLWriter(XMLWriter::STORAGE_DISK, $this->getParentWriter()->getDiskCachingDirectory());
25
        } else {
26 248
            $objWriter = new XMLWriter(XMLWriter::STORAGE_MEMORY);
27
        }
28
29
        // XML header
30 248
        $objWriter->startDocument('1.0', 'UTF-8', 'yes');
31
32
        // Relationships
33 248
        $objWriter->startElement('Relationships');
34 248
        $objWriter->writeAttribute('xmlns', Namespaces::RELATIONSHIPS);
35
36 248
        $customPropertyList = $spreadsheet->getProperties()->getCustomProperties();
37 248
        if (!empty($customPropertyList)) {
38
            // Relationship docProps/app.xml
39 11
            $this->writeRelationship(
40
                $objWriter,
41
                4,
42
                Namespaces::RELATIONSHIPS_CUSTOM_PROPERTIES,
43
                'docProps/custom.xml'
44
            );
45
        }
46
47
        // Relationship docProps/app.xml
48 248
        $this->writeRelationship(
49
            $objWriter,
50
            3,
51
            Namespaces::RELATIONSHIPS_EXTENDED_PROPERTIES,
52
            'docProps/app.xml'
53
        );
54
55
        // Relationship docProps/core.xml
56 248
        $this->writeRelationship(
57
            $objWriter,
58
            2,
59
            Namespaces::CORE_PROPERTIES,
60
            'docProps/core.xml'
61
        );
62
63
        // Relationship xl/workbook.xml
64 248
        $this->writeRelationship(
65
            $objWriter,
66
            1,
67
            Namespaces::OFFICE_DOCUMENT,
68
            'xl/workbook.xml'
69
        );
70
        // a custom UI in workbook ?
71 248
        $target = $spreadsheet->getRibbonXMLData('target');
72 248
        if ($spreadsheet->hasRibbon()) {
73 2
            $this->writeRelationShip(
74
                $objWriter,
75
                5,
76
                Namespaces::EXTENSIBILITY,
77 2
                is_string($target) ? $target : ''
78
            );
79
        }
80
81 248
        $objWriter->endElement();
82
83 248
        return $objWriter->getData();
84
    }
85
86
    /**
87
     * Write workbook relationships to XML format.
88
     *
89
     * @return string XML Output
90
     */
91 248
    public function writeWorkbookRelationships(Spreadsheet $spreadsheet)
92
    {
93
        // Create XML writer
94 248
        $objWriter = null;
95 248
        if ($this->getParentWriter()->getUseDiskCaching()) {
96
            $objWriter = new XMLWriter(XMLWriter::STORAGE_DISK, $this->getParentWriter()->getDiskCachingDirectory());
97
        } else {
98 248
            $objWriter = new XMLWriter(XMLWriter::STORAGE_MEMORY);
99
        }
100
101
        // XML header
102 248
        $objWriter->startDocument('1.0', 'UTF-8', 'yes');
103
104
        // Relationships
105 248
        $objWriter->startElement('Relationships');
106 248
        $objWriter->writeAttribute('xmlns', Namespaces::RELATIONSHIPS);
107
108
        // Relationship styles.xml
109 248
        $this->writeRelationship(
110
            $objWriter,
111
            1,
112
            Namespaces::STYLES,
113
            'styles.xml'
114
        );
115
116
        // Relationship theme/theme1.xml
117 248
        $this->writeRelationship(
118
            $objWriter,
119
            2,
120
            Namespaces::THEME2,
121
            'theme/theme1.xml'
122
        );
123
124
        // Relationship sharedStrings.xml
125 248
        $this->writeRelationship(
126
            $objWriter,
127
            3,
128
            Namespaces::SHARED_STRINGS,
129
            'sharedStrings.xml'
130
        );
131
132
        // Relationships with sheets
133 248
        $sheetCount = $spreadsheet->getSheetCount();
134 248
        for ($i = 0; $i < $sheetCount; ++$i) {
135 248
            $this->writeRelationship(
136
                $objWriter,
137
                ($i + 1 + 3),
138
                Namespaces::WORKSHEET,
139
                'worksheets/sheet' . ($i + 1) . '.xml'
140
            );
141
        }
142
        // Relationships for vbaProject if needed
143
        // id : just after the last sheet
144 248
        if ($spreadsheet->hasMacros()) {
145 2
            $this->writeRelationShip(
146
                $objWriter,
147
                ($i + 1 + 3),
148
                Namespaces::VBA,
149
                'vbaProject.bin'
150
            );
151 2
            ++$i; //increment i if needed for an another relation
152
        }
153
154 248
        $objWriter->endElement();
155
156 248
        return $objWriter->getData();
157
    }
158
159
    /**
160
     * Write worksheet relationships to XML format.
161
     *
162
     * Numbering is as follows:
163
     *     rId1                 - Drawings
164
     *  rId_hyperlink_x     - Hyperlinks
165
     *
166
     * @param int $worksheetId
167
     * @param bool $includeCharts Flag indicating if we should write charts
168
     * @param int $tableRef Table ID
169
     *
170
     * @return string XML Output
171
     */
172 247
    public function writeWorksheetRelationships(\PhpOffice\PhpSpreadsheet\Worksheet\Worksheet $worksheet, $worksheetId = 1, $includeCharts = false, $tableRef = 1)
173
    {
174
        // Create XML writer
175 247
        $objWriter = null;
176 247
        if ($this->getParentWriter()->getUseDiskCaching()) {
177
            $objWriter = new XMLWriter(XMLWriter::STORAGE_DISK, $this->getParentWriter()->getDiskCachingDirectory());
178
        } else {
179 247
            $objWriter = new XMLWriter(XMLWriter::STORAGE_MEMORY);
180
        }
181
182
        // XML header
183 247
        $objWriter->startDocument('1.0', 'UTF-8', 'yes');
184
185
        // Relationships
186 247
        $objWriter->startElement('Relationships');
187 247
        $objWriter->writeAttribute('xmlns', Namespaces::RELATIONSHIPS);
188
189
        // Write drawing relationships?
190 247
        $drawingOriginalIds = [];
191 247
        $unparsedLoadedData = $worksheet->getParent()->getUnparsedLoadedData();
192 247
        if (isset($unparsedLoadedData['sheets'][$worksheet->getCodeName()]['drawingOriginalIds'])) {
193 28
            $drawingOriginalIds = $unparsedLoadedData['sheets'][$worksheet->getCodeName()]['drawingOriginalIds'];
194
        }
195
196 247
        if ($includeCharts) {
197 54
            $charts = $worksheet->getChartCollection();
198
        } else {
199 193
            $charts = [];
200
        }
201
202 247
        if (($worksheet->getDrawingCollection()->count() > 0) || (count($charts) > 0) || $drawingOriginalIds) {
203 87
            $rId = 1;
204
205
            // Use original $relPath to get original $rId.
206
            // Take first. In future can be overwritten.
207
            // (! synchronize with \PhpOffice\PhpSpreadsheet\Writer\Xlsx\Worksheet::writeDrawings)
208 87
            reset($drawingOriginalIds);
209 87
            $relPath = key($drawingOriginalIds);
210 87
            if (isset($drawingOriginalIds[$relPath])) {
211 28
                $rId = (int) (substr($drawingOriginalIds[$relPath], 3));
212
            }
213
214
            // Generate new $relPath to write drawing relationship
215 87
            $relPath = '../drawings/drawing' . $worksheetId . '.xml';
216 87
            $this->writeRelationship(
217
                $objWriter,
218
                $rId,
219
                Namespaces::RELATIONSHIPS_DRAWING,
220
                $relPath
221
            );
222
        }
223
224
        // Write hyperlink relationships?
225 247
        $i = 1;
226 247
        foreach ($worksheet->getHyperlinkCollection() as $hyperlink) {
227 14
            if (!$hyperlink->isInternal()) {
228 14
                $this->writeRelationship(
229
                    $objWriter,
230
                    '_hyperlink_' . $i,
231
                    Namespaces::HYPERLINK,
232 14
                    $hyperlink->getUrl(),
233
                    'External'
234
                );
235
236 14
                ++$i;
237
            }
238
        }
239
240
        // Write comments relationship?
241 247
        $i = 1;
242 247
        if (count($worksheet->getComments()) > 0) {
243 16
            $this->writeRelationship(
244
                $objWriter,
245
                '_comments_vml' . $i,
246
                Namespaces::VML,
247
                '../drawings/vmlDrawing' . $worksheetId . '.vml'
248
            );
249
250 16
            $this->writeRelationship(
251
                $objWriter,
252
                '_comments' . $i,
253
                Namespaces::COMMENTS,
254
                '../comments' . $worksheetId . '.xml'
255
            );
256
        }
257
258
        // Write Table
259 247
        $tableCount = $worksheet->getTableCollection()->count();
260 247
        for ($i = 1; $i <= $tableCount; ++$i) {
261 3
            $this->writeRelationship(
262
                $objWriter,
263
                '_table_' . $i,
264
                Namespaces::RELATIONSHIPS_TABLE,
265
                '../tables/table' . $tableRef++ . '.xml'
266
            );
267
        }
268
269
        // Write header/footer relationship?
270 247
        $i = 1;
271 247
        if (count($worksheet->getHeaderFooter()->getImages()) > 0) {
272 3
            $this->writeRelationship(
273
                $objWriter,
274
                '_headerfooter_vml' . $i,
275
                Namespaces::VML,
276
                '../drawings/vmlDrawingHF' . $worksheetId . '.vml'
277
            );
278
        }
279
280 247
        $this->writeUnparsedRelationship($worksheet, $objWriter, 'ctrlProps', Namespaces::RELATIONSHIPS_CTRLPROP);
281 247
        $this->writeUnparsedRelationship($worksheet, $objWriter, 'vmlDrawings', Namespaces::VML);
282 247
        $this->writeUnparsedRelationship($worksheet, $objWriter, 'printerSettings', Namespaces::RELATIONSHIPS_PRINTER_SETTINGS);
283
284 247
        $objWriter->endElement();
285
286 247
        return $objWriter->getData();
287
    }
288
289 247
    private function writeUnparsedRelationship(\PhpOffice\PhpSpreadsheet\Worksheet\Worksheet $worksheet, XMLWriter $objWriter, string $relationship, string $type): void
290
    {
291 247
        $unparsedLoadedData = $worksheet->getParent()->getUnparsedLoadedData();
292 247
        if (!isset($unparsedLoadedData['sheets'][$worksheet->getCodeName()][$relationship])) {
293 247
            return;
294
        }
295
296 25
        foreach ($unparsedLoadedData['sheets'][$worksheet->getCodeName()][$relationship] as $rId => $value) {
297 25
            if (substr($rId, 0, 17) !== '_headerfooter_vml') {
298 25
                $this->writeRelationship(
299
                    $objWriter,
300
                    $rId,
301
                    $type,
302 25
                    $value['relFilePath']
303
                );
304
            }
305
        }
306
    }
307
308
    /**
309
     * Write drawing relationships to XML format.
310
     *
311
     * @param int $chartRef Chart ID
312
     * @param bool $includeCharts Flag indicating if we should write charts
313
     *
314
     * @return string XML Output
315
     */
316 84
    public function writeDrawingRelationships(\PhpOffice\PhpSpreadsheet\Worksheet\Worksheet $worksheet, &$chartRef, $includeCharts = false)
317
    {
318
        // Create XML writer
319 84
        $objWriter = null;
320 84
        if ($this->getParentWriter()->getUseDiskCaching()) {
321
            $objWriter = new XMLWriter(XMLWriter::STORAGE_DISK, $this->getParentWriter()->getDiskCachingDirectory());
322
        } else {
323 84
            $objWriter = new XMLWriter(XMLWriter::STORAGE_MEMORY);
324
        }
325
326
        // XML header
327 84
        $objWriter->startDocument('1.0', 'UTF-8', 'yes');
328
329
        // Relationships
330 84
        $objWriter->startElement('Relationships');
331 84
        $objWriter->writeAttribute('xmlns', Namespaces::RELATIONSHIPS);
332
333
        // Loop through images and write relationships
334 84
        $i = 1;
335 84
        $iterator = $worksheet->getDrawingCollection()->getIterator();
336 84
        while ($iterator->valid()) {
337 38
            $drawing = $iterator->current();
338
            if (
339
                $drawing instanceof \PhpOffice\PhpSpreadsheet\Worksheet\Drawing
340 38
                || $drawing instanceof MemoryDrawing
341
            ) {
342
                // Write relationship for image drawing
343 38
                $this->writeRelationship(
344
                    $objWriter,
345
                    $i,
346
                    Namespaces::IMAGE,
347 38
                    '../media/' . $drawing->getIndexedFilename()
348
                );
349
350 38
                $i = $this->writeDrawingHyperLink($objWriter, $drawing, $i);
351
            }
352
353 38
            $iterator->next();
354 38
            ++$i;
355
        }
356
357 84
        if ($includeCharts) {
358
            // Loop through charts and write relationships
359 53
            $chartCount = $worksheet->getChartCount();
360 53
            if ($chartCount > 0) {
361 53
                for ($c = 0; $c < $chartCount; ++$c) {
362 53
                    $this->writeRelationship(
363
                        $objWriter,
364
                        $i++,
365
                        Namespaces::RELATIONSHIPS_CHART,
366
                        '../charts/chart' . ++$chartRef . '.xml'
367
                    );
368
                }
369
            }
370
        }
371
372 84
        $objWriter->endElement();
373
374 84
        return $objWriter->getData();
375
    }
376
377
    /**
378
     * Write header/footer drawing relationships to XML format.
379
     *
380
     * @return string XML Output
381
     */
382 3
    public function writeHeaderFooterDrawingRelationships(\PhpOffice\PhpSpreadsheet\Worksheet\Worksheet $worksheet)
383
    {
384
        // Create XML writer
385 3
        $objWriter = null;
386 3
        if ($this->getParentWriter()->getUseDiskCaching()) {
387
            $objWriter = new XMLWriter(XMLWriter::STORAGE_DISK, $this->getParentWriter()->getDiskCachingDirectory());
388
        } else {
389 3
            $objWriter = new XMLWriter(XMLWriter::STORAGE_MEMORY);
390
        }
391
392
        // XML header
393 3
        $objWriter->startDocument('1.0', 'UTF-8', 'yes');
394
395
        // Relationships
396 3
        $objWriter->startElement('Relationships');
397 3
        $objWriter->writeAttribute('xmlns', Namespaces::RELATIONSHIPS);
398
399
        // Loop through images and write relationships
400 3
        foreach ($worksheet->getHeaderFooter()->getImages() as $key => $value) {
401
            // Write relationship for image drawing
402 3
            $this->writeRelationship(
403
                $objWriter,
404
                $key,
405
                Namespaces::IMAGE,
406 3
                '../media/' . $value->getIndexedFilename()
407
            );
408
        }
409
410 3
        $objWriter->endElement();
411
412 3
        return $objWriter->getData();
413
    }
414
415 16
    public function writeVMLDrawingRelationships(\PhpOffice\PhpSpreadsheet\Worksheet\Worksheet $worksheet): string
416
    {
417
        // Create XML writer
418 16
        $objWriter = null;
419 16
        if ($this->getParentWriter()->getUseDiskCaching()) {
420
            $objWriter = new XMLWriter(XMLWriter::STORAGE_DISK, $this->getParentWriter()->getDiskCachingDirectory());
421
        } else {
422 16
            $objWriter = new XMLWriter(XMLWriter::STORAGE_MEMORY);
423
        }
424
425
        // XML header
426 16
        $objWriter->startDocument('1.0', 'UTF-8', 'yes');
427
428
        // Relationships
429 16
        $objWriter->startElement('Relationships');
430 16
        $objWriter->writeAttribute('xmlns', Namespaces::RELATIONSHIPS);
431
432
        // Loop through images and write relationships
433 16
        foreach ($worksheet->getComments() as $comment) {
434 16
            if (!$comment->hasBackgroundImage()) {
435 14
                continue;
436
            }
437
438 3
            $bgImage = $comment->getBackgroundImage();
439 3
            $this->writeRelationship(
440
                $objWriter,
441 3
                $bgImage->getImageIndex(),
442
                Namespaces::IMAGE,
443 3
                '../media/' . $bgImage->getMediaFilename()
444
            );
445
        }
446
447 16
        $objWriter->endElement();
448
449 16
        return $objWriter->getData();
450
    }
451
452
    /**
453
     * Write Override content type.
454
     *
455
     * @param int|string $id Relationship ID. rId will be prepended!
456
     * @param string $type Relationship type
457
     * @param string $target Relationship target
458
     * @param string $targetMode Relationship target mode
459
     */
460 248
    private function writeRelationship(XMLWriter $objWriter, $id, $type, $target, $targetMode = ''): void
461
    {
462 248
        if ($type != '' && $target != '') {
463
            // Write relationship
464 248
            $objWriter->startElement('Relationship');
465 248
            $objWriter->writeAttribute('Id', 'rId' . $id);
466 248
            $objWriter->writeAttribute('Type', $type);
467 248
            $objWriter->writeAttribute('Target', $target);
468
469 248
            if ($targetMode != '') {
470 16
                $objWriter->writeAttribute('TargetMode', $targetMode);
471
            }
472
473 248
            $objWriter->endElement();
474
        } else {
475
            throw new WriterException('Invalid parameters passed.');
476
        }
477
    }
478
479 38
    private function writeDrawingHyperLink(XMLWriter $objWriter, BaseDrawing $drawing, int $i): int
480
    {
481 38
        if ($drawing->getHyperlink() === null) {
482 36
            return $i;
483
        }
484
485 2
        ++$i;
486 2
        $this->writeRelationship(
487
            $objWriter,
488
            $i,
489
            Namespaces::HYPERLINK,
490 2
            $drawing->getHyperlink()->getUrl(),
491 2
            $drawing->getHyperlink()->getTypeHyperlink()
492
        );
493
494 2
        return $i;
495
    }
496
}
497