Passed
Push — master ( c91c8c...4b8a92 )
by Owen
21:17
created

BaseDrawing::setWorksheet()   B

Complexity

Conditions 8
Paths 6

Size

Total Lines 31
Code Lines 17

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 16
CRAP Score 8

Importance

Changes 0
Metric Value
eloc 17
c 0
b 0
f 0
dl 0
loc 31
ccs 16
cts 16
cp 1
rs 8.4444
cc 8
nc 6
nop 2
crap 8
1
<?php
2
3
namespace PhpOffice\PhpSpreadsheet\Worksheet;
4
5
use PhpOffice\PhpSpreadsheet\Cell\Hyperlink;
6
use PhpOffice\PhpSpreadsheet\Exception as PhpSpreadsheetException;
7
use PhpOffice\PhpSpreadsheet\IComparable;
8
use PhpOffice\PhpSpreadsheet\Worksheet\Drawing\Shadow;
9
use SimpleXMLElement;
10
11
class BaseDrawing implements IComparable
12
{
13
    const EDIT_AS_ABSOLUTE = 'absolute';
14
    const EDIT_AS_ONECELL = 'oneCell';
15
    const EDIT_AS_TWOCELL = 'twoCell';
16
    private const VALID_EDIT_AS = [
17
        self::EDIT_AS_ABSOLUTE,
18
        self::EDIT_AS_ONECELL,
19
        self::EDIT_AS_TWOCELL,
20
    ];
21
22
    /**
23
     * The editAs attribute, used only with two cell anchor.
24
     */
25
    protected string $editAs = '';
26
27
    /**
28
     * Image counter.
29
     */
30
    private static int $imageCounter = 0;
31
32
    /**
33
     * Image index.
34
     */
35
    private int $imageIndex;
36
37
    /**
38
     * Name.
39
     */
40
    protected string $name = '';
41
42
    /**
43
     * Description.
44
     */
45
    protected string $description = '';
46
47
    /**
48
     * Worksheet.
49
     */
50
    protected ?Worksheet $worksheet = null;
51
52
    /**
53
     * Coordinates.
54
     */
55
    protected string $coordinates = 'A1';
56
57
    /**
58
     * Offset X.
59
     */
60
    protected int $offsetX = 0;
61
62
    /**
63
     * Offset Y.
64
     */
65
    protected int $offsetY = 0;
66
67
    /**
68
     * Coordinates2.
69
     */
70
    protected string $coordinates2 = '';
71
72
    /**
73
     * Offset X2.
74
     */
75
    protected int $offsetX2 = 0;
76
77
    /**
78
     * Offset Y2.
79
     */
80
    protected int $offsetY2 = 0;
81
82
    /**
83
     * Width.
84
     */
85
    protected int $width = 0;
86
87
    /**
88
     * Height.
89
     */
90
    protected int $height = 0;
91
92
    /**
93
     * Pixel width of image. See $width for the size the Drawing will be in the sheet.
94
     */
95
    protected int $imageWidth = 0;
96
97
    /**
98
     * Pixel width of image. See $height for the size the Drawing will be in the sheet.
99
     */
100
    protected int $imageHeight = 0;
101
102
    /**
103
     * Proportional resize.
104
     */
105
    protected bool $resizeProportional = true;
106
107
    /**
108
     * Rotation.
109
     */
110
    protected int $rotation = 0;
111
112
    protected bool $flipVertical = false;
113
114
    protected bool $flipHorizontal = false;
115
116
    /**
117
     * Shadow.
118
     */
119
    protected Shadow $shadow;
120
121
    /**
122
     * Image hyperlink.
123
     */
124
    private ?Hyperlink $hyperlink = null;
125
126
    /**
127
     * Image type.
128
     */
129
    protected int $type = IMAGETYPE_UNKNOWN;
130
131
    /** @var null|SimpleXMLElement|string[] */
132
    protected $srcRect = [];
133
134
    /**
135
     * Create a new BaseDrawing.
136
     */
137 190
    public function __construct()
138
    {
139
        // Initialise values
140 190
        $this->setShadow();
141
142
        // Set image index
143 190
        ++self::$imageCounter;
144 190
        $this->imageIndex = self::$imageCounter;
145
    }
146
147 43
    public function __destruct()
148
    {
149 43
        $this->worksheet = null;
150
    }
151
152 14
    public function getImageIndex(): int
153
    {
154 14
        return $this->imageIndex;
155
    }
156
157 56
    public function getName(): string
158
    {
159 56
        return $this->name;
160
    }
161
162 90
    public function setName(string $name): self
163
    {
164 90
        $this->name = $name;
165
166 90
        return $this;
167
    }
168
169 63
    public function getDescription(): string
170
    {
171 63
        return $this->description;
172
    }
173
174 75
    public function setDescription(string $description): self
175
    {
176 75
        $this->description = $description;
177
178 75
        return $this;
179
    }
180
181 7
    public function getWorksheet(): ?Worksheet
182
    {
183 7
        return $this->worksheet;
184
    }
185
186
    /**
187
     * Set Worksheet.
188
     *
189
     * @param bool $overrideOld If a Worksheet has already been assigned, overwrite it and remove image from old Worksheet?
190
     */
191 91
    public function setWorksheet(?Worksheet $worksheet = null, bool $overrideOld = false): self
192
    {
193 91
        if ($this->worksheet === null) {
194
            // Add drawing to \PhpOffice\PhpSpreadsheet\Worksheet\Worksheet
195 91
            if ($worksheet !== null && !($this instanceof Drawing && $this->getPath() === '')) {
196 91
                $this->worksheet = $worksheet;
197 91
                $this->worksheet->getCell($this->coordinates);
198 91
                $this->worksheet->getDrawingCollection()->append($this);
199
            }
200
        } else {
201 1
            if ($overrideOld) {
202
                // Remove drawing from old \PhpOffice\PhpSpreadsheet\Worksheet\Worksheet
203 1
                $iterator = $this->worksheet->getDrawingCollection()->getIterator();
204
205 1
                while ($iterator->valid()) {
206 1
                    if ($iterator->current()->getHashCode() === $this->getHashCode()) {
207 1
                        $this->worksheet->getDrawingCollection()->offsetUnset($iterator->key());
208 1
                        $this->worksheet = null;
209
210 1
                        break;
211
                    }
212
                }
213
214
                // Set new \PhpOffice\PhpSpreadsheet\Worksheet\Worksheet
215 1
                $this->setWorksheet($worksheet);
216
            } else {
217 1
                throw new PhpSpreadsheetException('A Worksheet has already been assigned. Drawings can only exist on one \\PhpOffice\\PhpSpreadsheet\\Worksheet.');
218
            }
219
        }
220
221 91
        return $this;
222
    }
223
224 72
    public function getCoordinates(): string
225
    {
226 72
        return $this->coordinates;
227
    }
228
229 89
    public function setCoordinates(string $coordinates): self
230
    {
231 89
        $this->coordinates = $coordinates;
232
233 89
        return $this;
234
    }
235
236 71
    public function getOffsetX(): int
237
    {
238 71
        return $this->offsetX;
239
    }
240
241 85
    public function setOffsetX(int $offsetX): self
242
    {
243 85
        $this->offsetX = $offsetX;
244
245 85
        return $this;
246
    }
247
248 71
    public function getOffsetY(): int
249
    {
250 71
        return $this->offsetY;
251
    }
252
253 70
    public function setOffsetY(int $offsetY): self
254
    {
255 70
        $this->offsetY = $offsetY;
256
257 70
        return $this;
258
    }
259
260 59
    public function getCoordinates2(): string
261
    {
262 59
        return $this->coordinates2;
263
    }
264
265 40
    public function setCoordinates2(string $coordinates2): self
266
    {
267 40
        $this->coordinates2 = $coordinates2;
268
269 40
        return $this;
270
    }
271
272 28
    public function getOffsetX2(): int
273
    {
274 28
        return $this->offsetX2;
275
    }
276
277 40
    public function setOffsetX2(int $offsetX2): self
278
    {
279 40
        $this->offsetX2 = $offsetX2;
280
281 40
        return $this;
282
    }
283
284 28
    public function getOffsetY2(): int
285
    {
286 28
        return $this->offsetY2;
287
    }
288
289 40
    public function setOffsetY2(int $offsetY2): self
290
    {
291 40
        $this->offsetY2 = $offsetY2;
292
293 40
        return $this;
294
    }
295
296 81
    public function getWidth(): int
297
    {
298 81
        return $this->width;
299
    }
300
301 64
    public function setWidth(int $width): self
302
    {
303
        // Resize proportional?
304 64
        if ($this->resizeProportional && $width != 0) {
305 2
            $ratio = $this->height / ($this->width != 0 ? $this->width : 1);
306 2
            $this->height = (int) round($ratio * $width);
307
        }
308
309
        // Set width
310 64
        $this->width = $width;
311
312 64
        return $this;
313
    }
314
315 78
    public function getHeight(): int
316
    {
317 78
        return $this->height;
318
    }
319
320 82
    public function setHeight(int $height): self
321
    {
322
        // Resize proportional?
323 82
        if ($this->resizeProportional && $height != 0) {
324 29
            $ratio = $this->width / ($this->height != 0 ? $this->height : 1);
325 29
            $this->width = (int) round($ratio * $height);
326
        }
327
328
        // Set height
329 82
        $this->height = $height;
330
331 82
        return $this;
332
    }
333
334
    /**
335
     * Set width and height with proportional resize.
336
     *
337
     * Example:
338
     * <code>
339
     * $objDrawing->setResizeProportional(true);
340
     * $objDrawing->setWidthAndHeight(160,120);
341
     * </code>
342
     *
343
     * @author Vincent@luo MSN:[email protected]
344
     */
345 4
    public function setWidthAndHeight(int $width, int $height): self
346
    {
347 4
        $xratio = $width / ($this->width != 0 ? $this->width : 1);
348 4
        $yratio = $height / ($this->height != 0 ? $this->height : 1);
349 4
        if ($this->resizeProportional && !($width == 0 || $height == 0)) {
350 1
            if (($xratio * $this->height) < $height) {
351 1
                $this->height = (int) ceil($xratio * $this->height);
352 1
                $this->width = $width;
353
            } else {
354 1
                $this->width = (int) ceil($yratio * $this->width);
355 1
                $this->height = $height;
356
            }
357
        } else {
358 4
            $this->width = $width;
359 4
            $this->height = $height;
360
        }
361
362 4
        return $this;
363
    }
364
365 2
    public function getResizeProportional(): bool
366
    {
367 2
        return $this->resizeProportional;
368
    }
369
370 70
    public function setResizeProportional(bool $resizeProportional): self
371
    {
372 70
        $this->resizeProportional = $resizeProportional;
373
374 70
        return $this;
375
    }
376
377 47
    public function getRotation(): int
378
    {
379 47
        return $this->rotation;
380
    }
381
382 67
    public function setRotation(int $rotation): self
383
    {
384 67
        $this->rotation = $rotation;
385
386 67
        return $this;
387
    }
388
389 57
    public function getShadow(): Shadow
390
    {
391 57
        return $this->shadow;
392
    }
393
394 190
    public function setShadow(?Shadow $shadow = null): self
395
    {
396 190
        $this->shadow = $shadow ?? new Shadow();
397
398 190
        return $this;
399
    }
400
401
    /**
402
     * Get hash code.
403
     *
404
     * @return string Hash code
405
     */
406 48
    public function getHashCode(): string
407
    {
408 48
        return md5(
409 48
            $this->name
410 48
            . $this->description
411 48
            . (($this->worksheet === null) ? '' : $this->worksheet->getHashCode())
412 48
            . $this->coordinates
413 48
            . $this->offsetX
414 48
            . $this->offsetY
415 48
            . $this->coordinates2
416 48
            . $this->offsetX2
417 48
            . $this->offsetY2
418 48
            . $this->width
419 48
            . $this->height
420 48
            . $this->rotation
421 48
            . $this->shadow->getHashCode()
422 48
            . __CLASS__
423 48
        );
424
    }
425
426
    /**
427
     * Implement PHP __clone to create a deep clone, not just a shallow copy.
428
     */
429 8
    public function __clone()
430
    {
431 8
        $vars = get_object_vars($this);
432 8
        foreach ($vars as $key => $value) {
433 8
            if ($key == 'worksheet') {
434 8
                $this->worksheet = null;
435 8
            } elseif (is_object($value)) {
436 8
                $this->$key = clone $value;
437
            } else {
438 8
                $this->$key = $value;
439
            }
440
        }
441
    }
442
443 2
    public function setHyperlink(?Hyperlink $hyperlink = null): void
444
    {
445 2
        $this->hyperlink = $hyperlink;
446
    }
447
448 47
    public function getHyperlink(): ?Hyperlink
449
    {
450 47
        return $this->hyperlink;
451
    }
452
453
    /**
454
     * Set Fact Sizes and Type of Image.
455
     */
456 43
    protected function setSizesAndType(string $path): void
457
    {
458 43
        if ($this->imageWidth === 0 && $this->imageHeight === 0 && $this->type === IMAGETYPE_UNKNOWN) {
459 43
            $imageData = getimagesize($path);
460
461 43
            if (!empty($imageData)) {
462 43
                $this->imageWidth = $imageData[0];
463 43
                $this->imageHeight = $imageData[1];
464 43
                $this->type = $imageData[2];
465
            }
466
        }
467 43
        if ($this->width === 0 && $this->height === 0) {
468 43
            $this->width = $this->imageWidth;
469 43
            $this->height = $this->imageHeight;
470
        }
471
    }
472
473
    /**
474
     * Get Image Type.
475
     */
476 5
    public function getType(): int
477
    {
478 5
        return $this->type;
479
    }
480
481 1
    public function getImageWidth(): int
482
    {
483 1
        return $this->imageWidth;
484
    }
485
486 1
    public function getImageHeight(): int
487
    {
488 1
        return $this->imageHeight;
489
    }
490
491 28
    public function getEditAs(): string
492
    {
493 28
        return $this->editAs;
494
    }
495
496 38
    public function setEditAs(string $editAs): self
497
    {
498 38
        $this->editAs = $editAs;
499
500 38
        return $this;
501
    }
502
503 28
    public function validEditAs(): bool
504
    {
505 28
        return in_array($this->editAs, self::VALID_EDIT_AS, true);
506
    }
507
508
    /**
509
     * @return null|SimpleXMLElement|string[]
510
     */
511 47
    public function getSrcRect()
512
    {
513 47
        return $this->srcRect;
514
    }
515
516
    /**
517
     * @param null|SimpleXMLElement|string[] $srcRect
518
     */
519 5
    public function setSrcRect($srcRect): self
520
    {
521 5
        $this->srcRect = $srcRect;
522
523 5
        return $this;
524
    }
525
526 52
    public function setFlipHorizontal(bool $flipHorizontal): self
527
    {
528 52
        $this->flipHorizontal = $flipHorizontal;
529
530 52
        return $this;
531
    }
532
533 47
    public function getFlipHorizontal(): bool
534
    {
535 47
        return $this->flipHorizontal;
536
    }
537
538 52
    public function setFlipVertical(bool $flipVertical): self
539
    {
540 52
        $this->flipVertical = $flipVertical;
541
542 52
        return $this;
543
    }
544
545 47
    public function getFlipVertical(): bool
546
    {
547 47
        return $this->flipVertical;
548
    }
549
}
550