Passed
Pull Request — master (#4142)
by Owen
16:30 queued 03:39
created

BaseDrawing::getHyperlink()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 0
dl 0
loc 3
rs 10
c 0
b 0
f 0
ccs 2
cts 2
cp 1
crap 1
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
     * Percentage multiplied by 100,000, e.g. 40% = 40,000.
136
     * Opacity=x is the same as transparency=100000-x.
137
     */
138
    protected ?int $opacity = null;
139
140
    /**
141
     * Create a new BaseDrawing.
142
     */
143 203
    public function __construct()
144
    {
145
        // Initialise values
146 203
        $this->setShadow();
147
148
        // Set image index
149 203
        ++self::$imageCounter;
150 203
        $this->imageIndex = self::$imageCounter;
151
    }
152
153 52
    public function __destruct()
154
    {
155 52
        $this->worksheet = null;
156
    }
157
158 14
    public function getImageIndex(): int
159
    {
160 14
        return $this->imageIndex;
161
    }
162
163 59
    public function getName(): string
164
    {
165 59
        return $this->name;
166
    }
167
168 99
    public function setName(string $name): self
169
    {
170 99
        $this->name = $name;
171
172 99
        return $this;
173
    }
174
175 69
    public function getDescription(): string
176
    {
177 69
        return $this->description;
178
    }
179
180 80
    public function setDescription(string $description): self
181
    {
182 80
        $this->description = $description;
183
184 80
        return $this;
185
    }
186
187 9
    public function getWorksheet(): ?Worksheet
188
    {
189 9
        return $this->worksheet;
190
    }
191
192
    /**
193
     * Set Worksheet.
194
     *
195
     * @param bool $overrideOld If a Worksheet has already been assigned, overwrite it and remove image from old Worksheet?
196
     */
197 99
    public function setWorksheet(?Worksheet $worksheet = null, bool $overrideOld = false): self
198
    {
199 99
        if ($this->worksheet === null) {
200
            // Add drawing to \PhpOffice\PhpSpreadsheet\Worksheet\Worksheet
201 99
            if ($worksheet !== null && !($this instanceof Drawing && $this->getPath() === '')) {
202 98
                $this->worksheet = $worksheet;
203 98
                $this->worksheet->getCell($this->coordinates);
204 98
                $this->worksheet->getDrawingCollection()->append($this);
205
            }
206
        } else {
207 1
            if ($overrideOld) {
208
                // Remove drawing from old \PhpOffice\PhpSpreadsheet\Worksheet\Worksheet
209 1
                $iterator = $this->worksheet->getDrawingCollection()->getIterator();
210
211 1
                while ($iterator->valid()) {
212 1
                    if ($iterator->current()->getHashCode() === $this->getHashCode()) {
213 1
                        $this->worksheet->getDrawingCollection()->offsetUnset($iterator->key());
214 1
                        $this->worksheet = null;
215
216 1
                        break;
217
                    }
218
                }
219
220
                // Set new \PhpOffice\PhpSpreadsheet\Worksheet\Worksheet
221 1
                $this->setWorksheet($worksheet);
222
            } else {
223 1
                throw new PhpSpreadsheetException('A Worksheet has already been assigned. Drawings can only exist on one \\PhpOffice\\PhpSpreadsheet\\Worksheet.');
224
            }
225
        }
226
227 99
        return $this;
228
    }
229
230 79
    public function getCoordinates(): string
231
    {
232 79
        return $this->coordinates;
233
    }
234
235 97
    public function setCoordinates(string $coordinates): self
236
    {
237 97
        $this->coordinates = $coordinates;
238
239 97
        return $this;
240
    }
241
242 77
    public function getOffsetX(): int
243
    {
244 77
        return $this->offsetX;
245
    }
246
247 88
    public function setOffsetX(int $offsetX): self
248
    {
249 88
        $this->offsetX = $offsetX;
250
251 88
        return $this;
252
    }
253
254 77
    public function getOffsetY(): int
255
    {
256 77
        return $this->offsetY;
257
    }
258
259 73
    public function setOffsetY(int $offsetY): self
260
    {
261 73
        $this->offsetY = $offsetY;
262
263 73
        return $this;
264
    }
265
266 62
    public function getCoordinates2(): string
267
    {
268 62
        return $this->coordinates2;
269
    }
270
271 45
    public function setCoordinates2(string $coordinates2): self
272
    {
273 45
        $this->coordinates2 = $coordinates2;
274
275 45
        return $this;
276
    }
277
278 30
    public function getOffsetX2(): int
279
    {
280 30
        return $this->offsetX2;
281
    }
282
283 41
    public function setOffsetX2(int $offsetX2): self
284
    {
285 41
        $this->offsetX2 = $offsetX2;
286
287 41
        return $this;
288
    }
289
290 30
    public function getOffsetY2(): int
291
    {
292 30
        return $this->offsetY2;
293
    }
294
295 41
    public function setOffsetY2(int $offsetY2): self
296
    {
297 41
        $this->offsetY2 = $offsetY2;
298
299 41
        return $this;
300
    }
301
302 89
    public function getWidth(): int
303
    {
304 89
        return $this->width;
305
    }
306
307 66
    public function setWidth(int $width): self
308
    {
309
        // Resize proportional?
310 66
        if ($this->resizeProportional && $width != 0) {
311 4
            $ratio = $this->height / ($this->width != 0 ? $this->width : 1);
312 4
            $this->height = (int) round($ratio * $width);
313
        }
314
315
        // Set width
316 66
        $this->width = $width;
317
318 66
        return $this;
319
    }
320
321 86
    public function getHeight(): int
322
    {
323 86
        return $this->height;
324
    }
325
326 84
    public function setHeight(int $height): self
327
    {
328
        // Resize proportional?
329 84
        if ($this->resizeProportional && $height != 0) {
330 29
            $ratio = $this->width / ($this->height != 0 ? $this->height : 1);
331 29
            $this->width = (int) round($ratio * $height);
332
        }
333
334
        // Set height
335 84
        $this->height = $height;
336
337 84
        return $this;
338
    }
339
340
    /**
341
     * Set width and height with proportional resize.
342
     *
343
     * Example:
344
     * <code>
345
     * $objDrawing->setResizeProportional(true);
346
     * $objDrawing->setWidthAndHeight(160,120);
347
     * </code>
348
     *
349
     * @author Vincent@luo MSN:[email protected]
350
     */
351 6
    public function setWidthAndHeight(int $width, int $height): self
352
    {
353 6
        if ($this->width === 0 || $this->height === 0 || $width === 0 || $height === 0 || !$this->resizeProportional) {
354 6
            $this->width = $width;
355 6
            $this->height = $height;
356
        } else {
357 1
            $xratio = $width / $this->width;
358 1
            $yratio = $height / $this->height;
359 1
            if (($xratio * $this->height) < $height) {
360 1
                $this->height = (int) ceil($xratio * $this->height);
361 1
                $this->width = $width;
362
            } else {
363 1
                $this->width = (int) ceil($yratio * $this->width);
364 1
                $this->height = $height;
365
            }
366
        }
367
368 6
        return $this;
369
    }
370
371 2
    public function getResizeProportional(): bool
372
    {
373 2
        return $this->resizeProportional;
374
    }
375
376 73
    public function setResizeProportional(bool $resizeProportional): self
377
    {
378 73
        $this->resizeProportional = $resizeProportional;
379
380 73
        return $this;
381
    }
382
383 50
    public function getRotation(): int
384
    {
385 50
        return $this->rotation;
386
    }
387
388 69
    public function setRotation(int $rotation): self
389
    {
390 69
        $this->rotation = $rotation;
391
392 69
        return $this;
393
    }
394
395 60
    public function getShadow(): Shadow
396
    {
397 60
        return $this->shadow;
398
    }
399
400 203
    public function setShadow(?Shadow $shadow = null): self
401
    {
402 203
        $this->shadow = $shadow ?? new Shadow();
403
404 203
        return $this;
405
    }
406
407
    /**
408
     * Get hash code.
409
     *
410
     * @return string Hash code
411
     */
412 51
    public function getHashCode(): string
413
    {
414 51
        return md5(
415 51
            $this->name
416 51
            . $this->description
417 51
            . (($this->worksheet === null) ? '' : $this->worksheet->getHashCode())
418 51
            . $this->coordinates
419 51
            . $this->offsetX
420 51
            . $this->offsetY
421 51
            . $this->coordinates2
422 51
            . $this->offsetX2
423 51
            . $this->offsetY2
424 51
            . $this->width
425 51
            . $this->height
426 51
            . $this->rotation
427 51
            . $this->shadow->getHashCode()
428 51
            . __CLASS__
429 51
        );
430
    }
431
432
    /**
433
     * Implement PHP __clone to create a deep clone, not just a shallow copy.
434
     */
435 8
    public function __clone()
436
    {
437 8
        $vars = get_object_vars($this);
438 8
        foreach ($vars as $key => $value) {
439 8
            if ($key == 'worksheet') {
440 8
                $this->worksheet = null;
441 8
            } elseif (is_object($value)) {
442 8
                $this->$key = clone $value;
443
            } else {
444 8
                $this->$key = $value;
445
            }
446
        }
447
    }
448
449 2
    public function setHyperlink(?Hyperlink $hyperlink = null): void
450
    {
451 2
        $this->hyperlink = $hyperlink;
452
    }
453
454 50
    public function getHyperlink(): ?Hyperlink
455
    {
456 50
        return $this->hyperlink;
457
    }
458
459
    /**
460
     * Set Fact Sizes and Type of Image.
461
     */
462 94
    protected function setSizesAndType(string $path): void
463
    {
464 94
        if ($this->imageWidth === 0 && $this->imageHeight === 0 && $this->type === IMAGETYPE_UNKNOWN) {
465 94
            $imageData = getimagesize($path);
466
467 94
            if (!empty($imageData)) {
468 92
                $this->imageWidth = $imageData[0];
469 92
                $this->imageHeight = $imageData[1];
470 92
                $this->type = $imageData[2];
471
            }
472
        }
473 94
        if ($this->width === 0 && $this->height === 0) {
474 94
            $this->width = $this->imageWidth;
475 94
            $this->height = $this->imageHeight;
476
        }
477
    }
478
479
    /**
480
     * Get Image Type.
481
     */
482 6
    public function getType(): int
483
    {
484 6
        return $this->type;
485
    }
486
487 1
    public function getImageWidth(): int
488
    {
489 1
        return $this->imageWidth;
490
    }
491
492 1
    public function getImageHeight(): int
493
    {
494 1
        return $this->imageHeight;
495
    }
496
497 28
    public function getEditAs(): string
498
    {
499 28
        return $this->editAs;
500
    }
501
502 40
    public function setEditAs(string $editAs): self
503
    {
504 40
        $this->editAs = $editAs;
505
506 40
        return $this;
507
    }
508
509 30
    public function validEditAs(): bool
510
    {
511 30
        return in_array($this->editAs, self::VALID_EDIT_AS, true);
512
    }
513
514
    /**
515
     * @return null|SimpleXMLElement|string[]
516
     */
517 50
    public function getSrcRect()
518
    {
519 50
        return $this->srcRect;
520
    }
521
522
    /**
523
     * @param null|SimpleXMLElement|string[] $srcRect
524
     */
525 7
    public function setSrcRect($srcRect): self
526
    {
527 7
        $this->srcRect = $srcRect;
528
529 7
        return $this;
530
    }
531
532 54
    public function setFlipHorizontal(bool $flipHorizontal): self
533
    {
534 54
        $this->flipHorizontal = $flipHorizontal;
535
536 54
        return $this;
537
    }
538
539 50
    public function getFlipHorizontal(): bool
540
    {
541 50
        return $this->flipHorizontal;
542
    }
543
544 54
    public function setFlipVertical(bool $flipVertical): self
545
    {
546 54
        $this->flipVertical = $flipVertical;
547
548 54
        return $this;
549
    }
550
551 50
    public function getFlipVertical(): bool
552
    {
553 50
        return $this->flipVertical;
554
    }
555
556 7
    public function setOpacity(?int $opacity): self
557
    {
558 7
        $this->opacity = $opacity;
559
560 7
        return $this;
561
    }
562
563 69
    public function getOpacity(): ?int
564
    {
565 69
        return $this->opacity;
566
    }
567
}
568