ILIAS  release_5-4 Revision v5.4.26-12-gabc799a52e6
Escher.php
Go to the documentation of this file.
1<?php
2
4
13
14class Escher
15{
19 private $object;
20
24 private $data;
25
31 private $spOffsets;
32
38 private $spTypes;
39
45 public function __construct($object)
46 {
47 $this->object = $object;
48 }
49
55 public function close()
56 {
57 // initialize
58 $this->data = '';
59
60 switch (get_class($this->object)) {
61 case \PhpOffice\PhpSpreadsheet\Shared\Escher::class:
62 if ($dggContainer = $this->object->getDggContainer()) {
63 $writer = new self($dggContainer);
64 $this->data = $writer->close();
65 } elseif ($dgContainer = $this->object->getDgContainer()) {
66 $writer = new self($dgContainer);
67 $this->data = $writer->close();
68 $this->spOffsets = $writer->getSpOffsets();
69 $this->spTypes = $writer->getSpTypes();
70 }
71
72 break;
73 case DggContainer::class:
74 // this is a container record
75
76 // initialize
77 $innerData = '';
78
79 // write the dgg
80 $recVer = 0x0;
81 $recInstance = 0x0000;
82 $recType = 0xF006;
83
84 $recVerInstance = $recVer;
85 $recVerInstance |= $recInstance << 4;
86
87 // dgg data
88 $dggData =
89 pack(
90 'VVVV',
91 $this->object->getSpIdMax(), // maximum shape identifier increased by one
92 $this->object->getCDgSaved() + 1, // number of file identifier clusters increased by one
93 $this->object->getCSpSaved(),
94 $this->object->getCDgSaved() // count total number of drawings saved
95 );
96
97 // add file identifier clusters (one per drawing)
98 $IDCLs = $this->object->getIDCLs();
99
100 foreach ($IDCLs as $dgId => $maxReducedSpId) {
101 $dggData .= pack('VV', $dgId, $maxReducedSpId + 1);
102 }
103
104 $header = pack('vvV', $recVerInstance, $recType, strlen($dggData));
105 $innerData .= $header . $dggData;
106
107 // write the bstoreContainer
108 if ($bstoreContainer = $this->object->getBstoreContainer()) {
109 $writer = new self($bstoreContainer);
110 $innerData .= $writer->close();
111 }
112
113 // write the record
114 $recVer = 0xF;
115 $recInstance = 0x0000;
116 $recType = 0xF000;
117 $length = strlen($innerData);
118
119 $recVerInstance = $recVer;
120 $recVerInstance |= $recInstance << 4;
121
122 $header = pack('vvV', $recVerInstance, $recType, $length);
123
124 $this->data = $header . $innerData;
125
126 break;
127 case BstoreContainer::class:
128 // this is a container record
129
130 // initialize
131 $innerData = '';
132
133 // treat the inner data
134 if ($BSECollection = $this->object->getBSECollection()) {
135 foreach ($BSECollection as $BSE) {
136 $writer = new self($BSE);
137 $innerData .= $writer->close();
138 }
139 }
140
141 // write the record
142 $recVer = 0xF;
143 $recInstance = count($this->object->getBSECollection());
144 $recType = 0xF001;
145 $length = strlen($innerData);
146
147 $recVerInstance = $recVer;
148 $recVerInstance |= $recInstance << 4;
149
150 $header = pack('vvV', $recVerInstance, $recType, $length);
151
152 $this->data = $header . $innerData;
153
154 break;
155 case BSE::class:
156 // this is a semi-container record
157
158 // initialize
159 $innerData = '';
160
161 // here we treat the inner data
162 if ($blip = $this->object->getBlip()) {
163 $writer = new self($blip);
164 $innerData .= $writer->close();
165 }
166
167 // initialize
168 $data = '';
169
170 $btWin32 = $this->object->getBlipType();
171 $btMacOS = $this->object->getBlipType();
172 $data .= pack('CC', $btWin32, $btMacOS);
173
174 $rgbUid = pack('VVVV', 0, 0, 0, 0); // todo
175 $data .= $rgbUid;
176
177 $tag = 0;
178 $size = strlen($innerData);
179 $cRef = 1;
180 $foDelay = 0; //todo
181 $unused1 = 0x0;
182 $cbName = 0x0;
183 $unused2 = 0x0;
184 $unused3 = 0x0;
185 $data .= pack('vVVVCCCC', $tag, $size, $cRef, $foDelay, $unused1, $cbName, $unused2, $unused3);
186
187 $data .= $innerData;
188
189 // write the record
190 $recVer = 0x2;
191 $recInstance = $this->object->getBlipType();
192 $recType = 0xF007;
193 $length = strlen($data);
194
195 $recVerInstance = $recVer;
196 $recVerInstance |= $recInstance << 4;
197
198 $header = pack('vvV', $recVerInstance, $recType, $length);
199
200 $this->data = $header;
201
202 $this->data .= $data;
203
204 break;
205 case Blip::class:
206 // this is an atom record
207
208 // write the record
209 switch ($this->object->getParent()->getBlipType()) {
211 // initialize
212 $innerData = '';
213
214 $rgbUid1 = pack('VVVV', 0, 0, 0, 0); // todo
215 $innerData .= $rgbUid1;
216
217 $tag = 0xFF; // todo
218 $innerData .= pack('C', $tag);
219
220 $innerData .= $this->object->getData();
221
222 $recVer = 0x0;
223 $recInstance = 0x46A;
224 $recType = 0xF01D;
225 $length = strlen($innerData);
226
227 $recVerInstance = $recVer;
228 $recVerInstance |= $recInstance << 4;
229
230 $header = pack('vvV', $recVerInstance, $recType, $length);
231
232 $this->data = $header;
233
234 $this->data .= $innerData;
235
236 break;
238 // initialize
239 $innerData = '';
240
241 $rgbUid1 = pack('VVVV', 0, 0, 0, 0); // todo
242 $innerData .= $rgbUid1;
243
244 $tag = 0xFF; // todo
245 $innerData .= pack('C', $tag);
246
247 $innerData .= $this->object->getData();
248
249 $recVer = 0x0;
250 $recInstance = 0x6E0;
251 $recType = 0xF01E;
252 $length = strlen($innerData);
253
254 $recVerInstance = $recVer;
255 $recVerInstance |= $recInstance << 4;
256
257 $header = pack('vvV', $recVerInstance, $recType, $length);
258
259 $this->data = $header;
260
261 $this->data .= $innerData;
262
263 break;
264 }
265
266 break;
267 case DgContainer::class:
268 // this is a container record
269
270 // initialize
271 $innerData = '';
272
273 // write the dg
274 $recVer = 0x0;
275 $recInstance = $this->object->getDgId();
276 $recType = 0xF008;
277 $length = 8;
278
279 $recVerInstance = $recVer;
280 $recVerInstance |= $recInstance << 4;
281
282 $header = pack('vvV', $recVerInstance, $recType, $length);
283
284 // number of shapes in this drawing (including group shape)
285 $countShapes = count($this->object->getSpgrContainer()->getChildren());
286 $innerData .= $header . pack('VV', $countShapes, $this->object->getLastSpId());
287
288 // write the spgrContainer
289 if ($spgrContainer = $this->object->getSpgrContainer()) {
290 $writer = new self($spgrContainer);
291 $innerData .= $writer->close();
292
293 // get the shape offsets relative to the spgrContainer record
294 $spOffsets = $writer->getSpOffsets();
295 $spTypes = $writer->getSpTypes();
296
297 // save the shape offsets relative to dgContainer
298 foreach ($spOffsets as &$spOffset) {
299 $spOffset += 24; // add length of dgContainer header data (8 bytes) plus dg data (16 bytes)
300 }
301
302 $this->spOffsets = $spOffsets;
303 $this->spTypes = $spTypes;
304 }
305
306 // write the record
307 $recVer = 0xF;
308 $recInstance = 0x0000;
309 $recType = 0xF002;
310 $length = strlen($innerData);
311
312 $recVerInstance = $recVer;
313 $recVerInstance |= $recInstance << 4;
314
315 $header = pack('vvV', $recVerInstance, $recType, $length);
316
317 $this->data = $header . $innerData;
318
319 break;
320 case SpgrContainer::class:
321 // this is a container record
322
323 // initialize
324 $innerData = '';
325
326 // initialize spape offsets
327 $totalSize = 8;
328 $spOffsets = [];
329 $spTypes = [];
330
331 // treat the inner data
332 foreach ($this->object->getChildren() as $spContainer) {
333 $writer = new self($spContainer);
334 $spData = $writer->close();
335 $innerData .= $spData;
336
337 // save the shape offsets (where new shape records begin)
338 $totalSize += strlen($spData);
339 $spOffsets[] = $totalSize;
340
341 $spTypes = array_merge($spTypes, $writer->getSpTypes());
342 }
343
344 // write the record
345 $recVer = 0xF;
346 $recInstance = 0x0000;
347 $recType = 0xF003;
348 $length = strlen($innerData);
349
350 $recVerInstance = $recVer;
351 $recVerInstance |= $recInstance << 4;
352
353 $header = pack('vvV', $recVerInstance, $recType, $length);
354
355 $this->data = $header . $innerData;
356 $this->spOffsets = $spOffsets;
357 $this->spTypes = $spTypes;
358
359 break;
360 case SpContainer::class:
361 // initialize
362 $data = '';
363
364 // build the data
365
366 // write group shape record, if necessary?
367 if ($this->object->getSpgr()) {
368 $recVer = 0x1;
369 $recInstance = 0x0000;
370 $recType = 0xF009;
371 $length = 0x00000010;
372
373 $recVerInstance = $recVer;
374 $recVerInstance |= $recInstance << 4;
375
376 $header = pack('vvV', $recVerInstance, $recType, $length);
377
378 $data .= $header . pack('VVVV', 0, 0, 0, 0);
379 }
380 $this->spTypes[] = ($this->object->getSpType());
381
382 // write the shape record
383 $recVer = 0x2;
384 $recInstance = $this->object->getSpType(); // shape type
385 $recType = 0xF00A;
386 $length = 0x00000008;
387
388 $recVerInstance = $recVer;
389 $recVerInstance |= $recInstance << 4;
390
391 $header = pack('vvV', $recVerInstance, $recType, $length);
392
393 $data .= $header . pack('VV', $this->object->getSpId(), $this->object->getSpgr() ? 0x0005 : 0x0A00);
394
395 // the options
396 if ($this->object->getOPTCollection()) {
397 $optData = '';
398
399 $recVer = 0x3;
400 $recInstance = count($this->object->getOPTCollection());
401 $recType = 0xF00B;
402 foreach ($this->object->getOPTCollection() as $property => $value) {
403 $optData .= pack('vV', $property, $value);
404 }
405 $length = strlen($optData);
406
407 $recVerInstance = $recVer;
408 $recVerInstance |= $recInstance << 4;
409
410 $header = pack('vvV', $recVerInstance, $recType, $length);
411 $data .= $header . $optData;
412 }
413
414 // the client anchor
415 if ($this->object->getStartCoordinates()) {
416 $clientAnchorData = '';
417
418 $recVer = 0x0;
419 $recInstance = 0x0;
420 $recType = 0xF010;
421
422 // start coordinates
423 [$column, $row] = Coordinate::indexesFromString($this->object->getStartCoordinates());
424 $c1 = $column - 1;
425 $r1 = $row - 1;
426
427 // start offsetX
428 $startOffsetX = $this->object->getStartOffsetX();
429
430 // start offsetY
431 $startOffsetY = $this->object->getStartOffsetY();
432
433 // end coordinates
434 [$column, $row] = Coordinate::indexesFromString($this->object->getEndCoordinates());
435 $c2 = $column - 1;
436 $r2 = $row - 1;
437
438 // end offsetX
439 $endOffsetX = $this->object->getEndOffsetX();
440
441 // end offsetY
442 $endOffsetY = $this->object->getEndOffsetY();
443
444 $clientAnchorData = pack('vvvvvvvvv', $this->object->getSpFlag(), $c1, $startOffsetX, $r1, $startOffsetY, $c2, $endOffsetX, $r2, $endOffsetY);
445
446 $length = strlen($clientAnchorData);
447
448 $recVerInstance = $recVer;
449 $recVerInstance |= $recInstance << 4;
450
451 $header = pack('vvV', $recVerInstance, $recType, $length);
452 $data .= $header . $clientAnchorData;
453 }
454
455 // the client data, just empty for now
456 if (!$this->object->getSpgr()) {
457 $clientDataData = '';
458
459 $recVer = 0x0;
460 $recInstance = 0x0;
461 $recType = 0xF011;
462
463 $length = strlen($clientDataData);
464
465 $recVerInstance = $recVer;
466 $recVerInstance |= $recInstance << 4;
467
468 $header = pack('vvV', $recVerInstance, $recType, $length);
469 $data .= $header . $clientDataData;
470 }
471
472 // write the record
473 $recVer = 0xF;
474 $recInstance = 0x0000;
475 $recType = 0xF004;
476 $length = strlen($data);
477
478 $recVerInstance = $recVer;
479 $recVerInstance |= $recInstance << 4;
480
481 $header = pack('vvV', $recVerInstance, $recType, $length);
482
483 $this->data = $header . $data;
484
485 break;
486 }
487
488 return $this->data;
489 }
490
496 public function getSpOffsets()
497 {
498 return $this->spOffsets;
499 }
500
506 public function getSpTypes()
507 {
508 return $this->spTypes;
509 }
510}
$size
Definition: RandomTest.php:84
An exception for terminatinating execution or to throw for unit testing.
Helper class to manipulate cell coordinates.
Definition: Coordinate.php:15
static indexesFromString(string $coordinates)
Get indexes from a string coordinates.
Definition: Coordinate.php:52
getSpTypes()
Gets the shape types.
Definition: Escher.php:506
getSpOffsets()
Gets the shape offsets.
Definition: Escher.php:496
$object
The object we are writing.
Definition: Escher.php:19
$data
The written binary data.
Definition: Escher.php:24
close()
Process the object to be written.
Definition: Escher.php:55
if(function_exists( 'posix_getuid') &&posix_getuid()===0) if(!array_key_exists('t', $options)) $tag
Definition: cron.php:35
$row
$this data['403_header']