Proyectos de Subversion Moodle

Rev

| Ultima modificación | Ver Log |

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