PluginProbe
wpDataTables – WordPress Data Table, Dynamic Tables & Table Charts Plugin / 6.5.1.7
wpDataTables – WordPress Data Table, Dynamic Tables & Table Charts Plugin v6.5.1.7
6.5.1.7 6.5.1.6 6.5.1.5 6.5.1.4 6.5.1.3 6.5.1.2 6.5.1.1 6.5.0.9 6.5.0.8 6.5.0.7 6.5.0.6 trunk 3.4.2.40 3.4.2.41 3.4.2.42 3.4.2.43 3.4.2.44 3.4.2.45 3.4.2.46 3.4.2.47 3.4.2.48 3.4.2.49 3.4.2.50 6.3.2 6.3.3.1 All 47 releases
wpdatatables / lib / phpoffice / phpspreadsheet / src / PhpSpreadsheet / Writer / Xlsx / Drawing.php

Drawing.php in wpDataTables – WordPress Data Table, Dynamic Tables & Table Charts Plugin 6.5.1.7, at lib/phpoffice/phpspreadsheet/src/PhpSpreadsheet/Writer/Xlsx/Drawing.php

572 lines 21.3 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace PhpOffice\PhpSpreadsheet\Writer\Xlsx;
4
5 use PhpOffice\PhpSpreadsheet\Cell\Coordinate;
6 use PhpOffice\PhpSpreadsheet\Reader\Xlsx\Namespaces;
7 use PhpOffice\PhpSpreadsheet\Shared\Drawing as SharedDrawing;
8 use PhpOffice\PhpSpreadsheet\Shared\XMLWriter;
9 use PhpOffice\PhpSpreadsheet\Spreadsheet;
10 use PhpOffice\PhpSpreadsheet\Worksheet\BaseDrawing;
11 use PhpOffice\PhpSpreadsheet\Worksheet\HeaderFooterDrawing;
12 use PhpOffice\PhpSpreadsheet\Writer\Exception as WriterException;
13
14 class Drawing extends WriterPart
15 {
16 /**
17 * Write drawings to XML format.
18 *
19 * @param bool $includeCharts Flag indicating if we should include drawing details for charts
20 *
21 * @return string XML Output
22 */
23 public function writeDrawings(\PhpOffice\PhpSpreadsheet\Worksheet\Worksheet $worksheet, $includeCharts = false)
24 {
25 // Create XML writer
26 $objWriter = null;
27 if ($this->getParentWriter()->getUseDiskCaching()) {
28 $objWriter = new XMLWriter(XMLWriter::STORAGE_DISK, $this->getParentWriter()->getDiskCachingDirectory());
29 } else {
30 $objWriter = new XMLWriter(XMLWriter::STORAGE_MEMORY);
31 }
32
33 // XML header
34 $objWriter->startDocument('1.0', 'UTF-8', 'yes');
35
36 // xdr:wsDr
37 $objWriter->startElement('xdr:wsDr');
38 $objWriter->writeAttribute('xmlns:xdr', Namespaces::SPREADSHEET_DRAWING);
39 $objWriter->writeAttribute('xmlns:a', Namespaces::DRAWINGML);
40
41 // Loop through images and write drawings
42 $i = 1;
43 $iterator = $worksheet->getDrawingCollection()->getIterator();
44 while ($iterator->valid()) {
45 /** @var BaseDrawing $pDrawing */
46 $pDrawing = $iterator->current();
47 $pRelationId = $i;
48 $hlinkClickId = $pDrawing->getHyperlink() === null ? null : ++$i;
49
50 $this->writeDrawing($objWriter, $pDrawing, $pRelationId, $hlinkClickId);
51
52 $iterator->next();
53 ++$i;
54 }
55
56 if ($includeCharts) {
57 $chartCount = $worksheet->getChartCount();
58 // Loop through charts and write the chart position
59 if ($chartCount > 0) {
60 for ($c = 0; $c < $chartCount; ++$c) {
61 $chart = $worksheet->getChartByIndex((string) $c);
62 if ($chart !== false) {
63 $this->writeChart($objWriter, $chart, $c + $i);
64 }
65 }
66 }
67 }
68
69 // unparsed AlternateContent
70 $unparsedLoadedData = $worksheet->getParentOrThrow()->getUnparsedLoadedData();
71 if (isset($unparsedLoadedData['sheets'][$worksheet->getCodeName()]['drawingAlternateContents'])) {
72 foreach ($unparsedLoadedData['sheets'][$worksheet->getCodeName()]['drawingAlternateContents'] as $drawingAlternateContent) {
73 $objWriter->writeRaw($drawingAlternateContent);
74 }
75 }
76
77 $objWriter->endElement();
78
79 // Return
80 return $objWriter->getData();
81 }
82
83 /**
84 * Write drawings to XML format.
85 *
86 * @param int $relationId
87 */
88 public function writeChart(XMLWriter $objWriter, \PhpOffice\PhpSpreadsheet\Chart\Chart $chart, $relationId = -1): void
89 {
90 $tl = $chart->getTopLeftPosition();
91 $tlColRow = Coordinate::indexesFromString($tl['cell']);
92 $br = $chart->getBottomRightPosition();
93
94 $isTwoCellAnchor = $br['cell'] !== '';
95 if ($isTwoCellAnchor) {
96 $brColRow = Coordinate::indexesFromString($br['cell']);
97
98 $objWriter->startElement('xdr:twoCellAnchor');
99
100 $objWriter->startElement('xdr:from');
101 $objWriter->writeElement('xdr:col', (string) ($tlColRow[0] - 1));
102 $objWriter->writeElement('xdr:colOff', self::stringEmu($tl['xOffset']));
103 $objWriter->writeElement('xdr:row', (string) ($tlColRow[1] - 1));
104 $objWriter->writeElement('xdr:rowOff', self::stringEmu($tl['yOffset']));
105 $objWriter->endElement();
106 $objWriter->startElement('xdr:to');
107 $objWriter->writeElement('xdr:col', (string) ($brColRow[0] - 1));
108 $objWriter->writeElement('xdr:colOff', self::stringEmu($br['xOffset']));
109 $objWriter->writeElement('xdr:row', (string) ($brColRow[1] - 1));
110 $objWriter->writeElement('xdr:rowOff', self::stringEmu($br['yOffset']));
111 $objWriter->endElement();
112 } elseif ($chart->getOneCellAnchor()) {
113 $objWriter->startElement('xdr:oneCellAnchor');
114
115 $objWriter->startElement('xdr:from');
116 $objWriter->writeElement('xdr:col', (string) ($tlColRow[0] - 1));
117 $objWriter->writeElement('xdr:colOff', self::stringEmu($tl['xOffset']));
118 $objWriter->writeElement('xdr:row', (string) ($tlColRow[1] - 1));
119 $objWriter->writeElement('xdr:rowOff', self::stringEmu($tl['yOffset']));
120 $objWriter->endElement();
121 $objWriter->startElement('xdr:ext');
122 $objWriter->writeAttribute('cx', self::stringEmu($br['xOffset']));
123 $objWriter->writeAttribute('cy', self::stringEmu($br['yOffset']));
124 $objWriter->endElement();
125 } else {
126 $objWriter->startElement('xdr:absoluteAnchor');
127 $objWriter->startElement('xdr:pos');
128 $objWriter->writeAttribute('x', '0');
129 $objWriter->writeAttribute('y', '0');
130 $objWriter->endElement();
131 $objWriter->startElement('xdr:ext');
132 $objWriter->writeAttribute('cx', self::stringEmu($br['xOffset']));
133 $objWriter->writeAttribute('cy', self::stringEmu($br['yOffset']));
134 $objWriter->endElement();
135 }
136
137 $objWriter->startElement('xdr:graphicFrame');
138 $objWriter->writeAttribute('macro', '');
139 $objWriter->startElement('xdr:nvGraphicFramePr');
140 $objWriter->startElement('xdr:cNvPr');
141 $objWriter->writeAttribute('name', 'Chart ' . $relationId);
142 $objWriter->writeAttribute('id', (string) (1025 * $relationId));
143 $objWriter->endElement();
144 $objWriter->startElement('xdr:cNvGraphicFramePr');
145 $objWriter->startElement('a:graphicFrameLocks');
146 $objWriter->endElement();
147 $objWriter->endElement();
148 $objWriter->endElement();
149
150 $objWriter->startElement('xdr:xfrm');
151 $objWriter->startElement('a:off');
152 $objWriter->writeAttribute('x', '0');
153 $objWriter->writeAttribute('y', '0');
154 $objWriter->endElement();
155 $objWriter->startElement('a:ext');
156 $objWriter->writeAttribute('cx', '0');
157 $objWriter->writeAttribute('cy', '0');
158 $objWriter->endElement();
159 $objWriter->endElement();
160
161 $objWriter->startElement('a:graphic');
162 $objWriter->startElement('a:graphicData');
163 $objWriter->writeAttribute('uri', Namespaces::CHART);
164 $objWriter->startElement('c:chart');
165 $objWriter->writeAttribute('xmlns:c', Namespaces::CHART);
166 $objWriter->writeAttribute('xmlns:r', Namespaces::SCHEMA_OFFICE_DOCUMENT);
167 $objWriter->writeAttribute('r:id', 'rId' . $relationId);
168 $objWriter->endElement();
169 $objWriter->endElement();
170 $objWriter->endElement();
171 $objWriter->endElement();
172
173 $objWriter->startElement('xdr:clientData');
174 $objWriter->endElement();
175
176 $objWriter->endElement();
177 }
178
179 /**
180 * Write drawings to XML format.
181 *
182 * @param int $relationId
183 * @param null|int $hlinkClickId
184 */
185 public function writeDrawing(XMLWriter $objWriter, BaseDrawing $drawing, $relationId = -1, $hlinkClickId = null): void
186 {
187 if ($relationId >= 0) {
188 $isTwoCellAnchor = $drawing->getCoordinates2() !== '';
189 if ($isTwoCellAnchor) {
190 // xdr:twoCellAnchor
191 $objWriter->startElement('xdr:twoCellAnchor');
192 if ($drawing->validEditAs()) {
193 $objWriter->writeAttribute('editAs', $drawing->getEditAs());
194 }
195 // Image location
196 $aCoordinates = Coordinate::indexesFromString($drawing->getCoordinates());
197 $aCoordinates2 = Coordinate::indexesFromString($drawing->getCoordinates2());
198
199 // xdr:from
200 $objWriter->startElement('xdr:from');
201 $objWriter->writeElement('xdr:col', (string) ($aCoordinates[0] - 1));
202 $objWriter->writeElement('xdr:colOff', self::stringEmu($drawing->getOffsetX()));
203 $objWriter->writeElement('xdr:row', (string) ($aCoordinates[1] - 1));
204 $objWriter->writeElement('xdr:rowOff', self::stringEmu($drawing->getOffsetY()));
205 $objWriter->endElement();
206
207 // xdr:to
208 $objWriter->startElement('xdr:to');
209 $objWriter->writeElement('xdr:col', (string) ($aCoordinates2[0] - 1));
210 $objWriter->writeElement('xdr:colOff', self::stringEmu($drawing->getOffsetX2()));
211 $objWriter->writeElement('xdr:row', (string) ($aCoordinates2[1] - 1));
212 $objWriter->writeElement('xdr:rowOff', self::stringEmu($drawing->getOffsetY2()));
213 $objWriter->endElement();
214 } else {
215 // xdr:oneCellAnchor
216 $objWriter->startElement('xdr:oneCellAnchor');
217 // Image location
218 $aCoordinates = Coordinate::indexesFromString($drawing->getCoordinates());
219
220 // xdr:from
221 $objWriter->startElement('xdr:from');
222 $objWriter->writeElement('xdr:col', (string) ($aCoordinates[0] - 1));
223 $objWriter->writeElement('xdr:colOff', self::stringEmu($drawing->getOffsetX()));
224 $objWriter->writeElement('xdr:row', (string) ($aCoordinates[1] - 1));
225 $objWriter->writeElement('xdr:rowOff', self::stringEmu($drawing->getOffsetY()));
226 $objWriter->endElement();
227
228 // xdr:ext
229 $objWriter->startElement('xdr:ext');
230 $objWriter->writeAttribute('cx', self::stringEmu($drawing->getWidth()));
231 $objWriter->writeAttribute('cy', self::stringEmu($drawing->getHeight()));
232 $objWriter->endElement();
233 }
234
235 // xdr:pic
236 $objWriter->startElement('xdr:pic');
237
238 // xdr:nvPicPr
239 $objWriter->startElement('xdr:nvPicPr');
240
241 // xdr:cNvPr
242 $objWriter->startElement('xdr:cNvPr');
243 $objWriter->writeAttribute('id', (string) $relationId);
244 $objWriter->writeAttribute('name', $drawing->getName());
245 $objWriter->writeAttribute('descr', $drawing->getDescription());
246
247 //a:hlinkClick
248 $this->writeHyperLinkDrawing($objWriter, $hlinkClickId);
249
250 $objWriter->endElement();
251
252 // xdr:cNvPicPr
253 $objWriter->startElement('xdr:cNvPicPr');
254
255 // a:picLocks
256 $objWriter->startElement('a:picLocks');
257 $objWriter->writeAttribute('noChangeAspect', '1');
258 $objWriter->endElement();
259
260 $objWriter->endElement();
261
262 $objWriter->endElement();
263
264 // xdr:blipFill
265 $objWriter->startElement('xdr:blipFill');
266
267 // a:blip
268 $objWriter->startElement('a:blip');
269 $objWriter->writeAttribute('xmlns:r', Namespaces::SCHEMA_OFFICE_DOCUMENT);
270 $objWriter->writeAttribute('r:embed', 'rId' . $relationId);
271 $objWriter->endElement();
272
273 // a:stretch
274 $objWriter->startElement('a:stretch');
275 $objWriter->writeElement('a:fillRect', null);
276 $objWriter->endElement();
277
278 $objWriter->endElement();
279
280 // xdr:spPr
281 $objWriter->startElement('xdr:spPr');
282
283 // a:xfrm
284 $objWriter->startElement('a:xfrm');
285 $objWriter->writeAttribute('rot', (string) SharedDrawing::degreesToAngle($drawing->getRotation()));
286 if ($isTwoCellAnchor) {
287 $objWriter->startElement('a:ext');
288 $objWriter->writeAttribute('cx', self::stringEmu($drawing->getWidth()));
289 $objWriter->writeAttribute('cy', self::stringEmu($drawing->getHeight()));
290 $objWriter->endElement();
291 }
292 $objWriter->endElement();
293
294 // a:prstGeom
295 $objWriter->startElement('a:prstGeom');
296 $objWriter->writeAttribute('prst', 'rect');
297
298 // a:avLst
299 $objWriter->writeElement('a:avLst', null);
300
301 $objWriter->endElement();
302
303 if ($drawing->getShadow()->getVisible()) {
304 // a:effectLst
305 $objWriter->startElement('a:effectLst');
306
307 // a:outerShdw
308 $objWriter->startElement('a:outerShdw');
309 $objWriter->writeAttribute('blurRad', self::stringEmu($drawing->getShadow()->getBlurRadius()));
310 $objWriter->writeAttribute('dist', self::stringEmu($drawing->getShadow()->getDistance()));
311 $objWriter->writeAttribute('dir', (string) SharedDrawing::degreesToAngle($drawing->getShadow()->getDirection()));
312 $objWriter->writeAttribute('algn', $drawing->getShadow()->getAlignment());
313 $objWriter->writeAttribute('rotWithShape', '0');
314
315 // a:srgbClr
316 $objWriter->startElement('a:srgbClr');
317 $objWriter->writeAttribute('val', $drawing->getShadow()->getColor()->getRGB());
318
319 // a:alpha
320 $objWriter->startElement('a:alpha');
321 $objWriter->writeAttribute('val', (string) ($drawing->getShadow()->getAlpha() * 1000));
322 $objWriter->endElement();
323
324 $objWriter->endElement();
325
326 $objWriter->endElement();
327
328 $objWriter->endElement();
329 }
330 $objWriter->endElement();
331
332 $objWriter->endElement();
333
334 // xdr:clientData
335 $objWriter->writeElement('xdr:clientData', null);
336
337 $objWriter->endElement();
338 } else {
339 throw new WriterException('Invalid parameters passed.');
340 }
341 }
342
343 /**
344 * Write VML header/footer images to XML format.
345 *
346 * @return string XML Output
347 */
348 public function writeVMLHeaderFooterImages(\PhpOffice\PhpSpreadsheet\Worksheet\Worksheet $worksheet)
349 {
350 // Create XML writer
351 $objWriter = null;
352 if ($this->getParentWriter()->getUseDiskCaching()) {
353 $objWriter = new XMLWriter(XMLWriter::STORAGE_DISK, $this->getParentWriter()->getDiskCachingDirectory());
354 } else {
355 $objWriter = new XMLWriter(XMLWriter::STORAGE_MEMORY);
356 }
357
358 // XML header
359 $objWriter->startDocument('1.0', 'UTF-8', 'yes');
360
361 // Header/footer images
362 $images = $worksheet->getHeaderFooter()->getImages();
363
364 // xml
365 $objWriter->startElement('xml');
366 $objWriter->writeAttribute('xmlns:v', Namespaces::URN_VML);
367 $objWriter->writeAttribute('xmlns:o', Namespaces::URN_MSOFFICE);
368 $objWriter->writeAttribute('xmlns:x', Namespaces::URN_EXCEL);
369
370 // o:shapelayout
371 $objWriter->startElement('o:shapelayout');
372 $objWriter->writeAttribute('v:ext', 'edit');
373
374 // o:idmap
375 $objWriter->startElement('o:idmap');
376 $objWriter->writeAttribute('v:ext', 'edit');
377 $objWriter->writeAttribute('data', '1');
378 $objWriter->endElement();
379
380 $objWriter->endElement();
381
382 // v:shapetype
383 $objWriter->startElement('v:shapetype');
384 $objWriter->writeAttribute('id', '_x0000_t75');
385 $objWriter->writeAttribute('coordsize', '21600,21600');
386 $objWriter->writeAttribute('o:spt', '75');
387 $objWriter->writeAttribute('o:preferrelative', 't');
388 $objWriter->writeAttribute('path', 'm@4@5l@4@11@9@11@9@5xe');
389 $objWriter->writeAttribute('filled', 'f');
390 $objWriter->writeAttribute('stroked', 'f');
391
392 // v:stroke
393 $objWriter->startElement('v:stroke');
394 $objWriter->writeAttribute('joinstyle', 'miter');
395 $objWriter->endElement();
396
397 // v:formulas
398 $objWriter->startElement('v:formulas');
399
400 // v:f
401 $objWriter->startElement('v:f');
402 $objWriter->writeAttribute('eqn', 'if lineDrawn pixelLineWidth 0');
403 $objWriter->endElement();
404
405 // v:f
406 $objWriter->startElement('v:f');
407 $objWriter->writeAttribute('eqn', 'sum @0 1 0');
408 $objWriter->endElement();
409
410 // v:f
411 $objWriter->startElement('v:f');
412 $objWriter->writeAttribute('eqn', 'sum 0 0 @1');
413 $objWriter->endElement();
414
415 // v:f
416 $objWriter->startElement('v:f');
417 $objWriter->writeAttribute('eqn', 'prod @2 1 2');
418 $objWriter->endElement();
419
420 // v:f
421 $objWriter->startElement('v:f');
422 $objWriter->writeAttribute('eqn', 'prod @3 21600 pixelWidth');
423 $objWriter->endElement();
424
425 // v:f
426 $objWriter->startElement('v:f');
427 $objWriter->writeAttribute('eqn', 'prod @3 21600 pixelHeight');
428 $objWriter->endElement();
429
430 // v:f
431 $objWriter->startElement('v:f');
432 $objWriter->writeAttribute('eqn', 'sum @0 0 1');
433 $objWriter->endElement();
434
435 // v:f
436 $objWriter->startElement('v:f');
437 $objWriter->writeAttribute('eqn', 'prod @6 1 2');
438 $objWriter->endElement();
439
440 // v:f
441 $objWriter->startElement('v:f');
442 $objWriter->writeAttribute('eqn', 'prod @7 21600 pixelWidth');
443 $objWriter->endElement();
444
445 // v:f
446 $objWriter->startElement('v:f');
447 $objWriter->writeAttribute('eqn', 'sum @8 21600 0');
448 $objWriter->endElement();
449
450 // v:f
451 $objWriter->startElement('v:f');
452 $objWriter->writeAttribute('eqn', 'prod @7 21600 pixelHeight');
453 $objWriter->endElement();
454
455 // v:f
456 $objWriter->startElement('v:f');
457 $objWriter->writeAttribute('eqn', 'sum @10 21600 0');
458 $objWriter->endElement();
459
460 $objWriter->endElement();
461
462 // v:path
463 $objWriter->startElement('v:path');
464 $objWriter->writeAttribute('o:extrusionok', 'f');
465 $objWriter->writeAttribute('gradientshapeok', 't');
466 $objWriter->writeAttribute('o:connecttype', 'rect');
467 $objWriter->endElement();
468
469 // o:lock
470 $objWriter->startElement('o:lock');
471 $objWriter->writeAttribute('v:ext', 'edit');
472 $objWriter->writeAttribute('aspectratio', 't');
473 $objWriter->endElement();
474
475 $objWriter->endElement();
476
477 // Loop through images
478 foreach ($images as $key => $value) {
479 $this->writeVMLHeaderFooterImage($objWriter, $key, $value);
480 }
481
482 $objWriter->endElement();
483
484 // Return
485 return $objWriter->getData();
486 }
487
488 /**
489 * Write VML comment to XML format.
490 *
491 * @param string $reference Reference
492 */
493 private function writeVMLHeaderFooterImage(XMLWriter $objWriter, $reference, HeaderFooterDrawing $image): void
494 {
495 // Calculate object id
496 preg_match('{(\d+)}', md5($reference), $m);
497 $id = 1500 + ((int) substr($m[1], 0, 2) * 1);
498
499 // Calculate offset
500 $width = $image->getWidth();
501 $height = $image->getHeight();
502 $marginLeft = $image->getOffsetX();
503 $marginTop = $image->getOffsetY();
504
505 // v:shape
506 $objWriter->startElement('v:shape');
507 $objWriter->writeAttribute('id', $reference);
508 $objWriter->writeAttribute('o:spid', '_x0000_s' . $id);
509 $objWriter->writeAttribute('type', '#_x0000_t75');
510 $objWriter->writeAttribute('style', "position:absolute;margin-left:{$marginLeft}px;margin-top:{$marginTop}px;width:{$width}px;height:{$height}px;z-index:1");
511
512 // v:imagedata
513 $objWriter->startElement('v:imagedata');
514 $objWriter->writeAttribute('o:relid', 'rId' . $reference);
515 $objWriter->writeAttribute('o:title', $image->getName());
516 $objWriter->endElement();
517
518 // o:lock
519 $objWriter->startElement('o:lock');
520 $objWriter->writeAttribute('v:ext', 'edit');
521 $objWriter->writeAttribute('textRotation', 't');
522 $objWriter->endElement();
523
524 $objWriter->endElement();
525 }
526
527 /**
528 * Get an array of all drawings.
529 *
530 * @return BaseDrawing[] All drawings in PhpSpreadsheet
531 */
532 public function allDrawings(Spreadsheet $spreadsheet)
533 {
534 // Get an array of all drawings
535 $aDrawings = [];
536
537 // Loop through PhpSpreadsheet
538 $sheetCount = $spreadsheet->getSheetCount();
539 for ($i = 0; $i < $sheetCount; ++$i) {
540 // Loop through images and add to array
541 $iterator = $spreadsheet->getSheet($i)->getDrawingCollection()->getIterator();
542 while ($iterator->valid()) {
543 $aDrawings[] = $iterator->current();
544
545 $iterator->next();
546 }
547 }
548
549 return $aDrawings;
550 }
551
552 /**
553 * @param null|int $hlinkClickId
554 */
555 private function writeHyperLinkDrawing(XMLWriter $objWriter, $hlinkClickId): void
556 {
557 if ($hlinkClickId === null) {
558 return;
559 }
560
561 $objWriter->startElement('a:hlinkClick');
562 $objWriter->writeAttribute('xmlns:r', Namespaces::SCHEMA_OFFICE_DOCUMENT);
563 $objWriter->writeAttribute('r:id', 'rId' . $hlinkClickId);
564 $objWriter->endElement();
565 }
566
567 private static function stringEmu(int $pixelValue): string
568 {
569 return (string) SharedDrawing::pixelsToEMU($pixelValue);
570 }
571 }
572