Search moodle.org's
Developer Documentation

See Release Notes
Long Term Support Release

  • Bug fixes for general core bugs in 4.1.x will end 13 November 2023 (12 months).
  • Bug fixes for security issues in 4.1.x will end 10 November 2025 (36 months).
  • PHP version: minimum PHP 7.4.0 Note: minimum PHP version has increased since Moodle 4.0. PHP 8.0.x is supported too.

Differences Between: [Versions 310 and 401] [Versions 311 and 401] [Versions 39 and 401] [Versions 400 and 401] [Versions 401 and 402] [Versions 401 and 403]

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