1<?php 2 3namespace PhpOffice\PhpSpreadsheet\Document; 4 5class Properties 6{ 7 /** constants */ 8 const PROPERTY_TYPE_BOOLEAN = 'b'; 9 const PROPERTY_TYPE_INTEGER = 'i'; 10 const PROPERTY_TYPE_FLOAT = 'f'; 11 const PROPERTY_TYPE_DATE = 'd'; 12 const PROPERTY_TYPE_STRING = 's'; 13 const PROPERTY_TYPE_UNKNOWN = 'u'; 14 15 /** 16 * Creator. 17 * 18 * @var string 19 */ 20 private $creator = 'Unknown Creator'; 21 22 /** 23 * LastModifiedBy. 24 * 25 * @var string 26 */ 27 private $lastModifiedBy; 28 29 /** 30 * Created. 31 * 32 * @var int 33 */ 34 private $created; 35 36 /** 37 * Modified. 38 * 39 * @var int 40 */ 41 private $modified; 42 43 /** 44 * Title. 45 * 46 * @var string 47 */ 48 private $title = 'Untitled Spreadsheet'; 49 50 /** 51 * Description. 52 * 53 * @var string 54 */ 55 private $description = ''; 56 57 /** 58 * Subject. 59 * 60 * @var string 61 */ 62 private $subject = ''; 63 64 /** 65 * Keywords. 66 * 67 * @var string 68 */ 69 private $keywords = ''; 70 71 /** 72 * Category. 73 * 74 * @var string 75 */ 76 private $category = ''; 77 78 /** 79 * Manager. 80 * 81 * @var string 82 */ 83 private $manager = ''; 84 85 /** 86 * Company. 87 * 88 * @var string 89 */ 90 private $company = 'Microsoft Corporation'; 91 92 /** 93 * Custom Properties. 94 * 95 * @var string 96 */ 97 private $customProperties = []; 98 99 /** 100 * Create a new Document Properties instance. 101 */ 102 public function __construct() 103 { 104 // Initialise values 105 $this->lastModifiedBy = $this->creator; 106 $this->created = time(); 107 $this->modified = time(); 108 } 109 110 /** 111 * Get Creator. 112 * 113 * @return string 114 */ 115 public function getCreator() 116 { 117 return $this->creator; 118 } 119 120 /** 121 * Set Creator. 122 * 123 * @param string $creator 124 * 125 * @return $this 126 */ 127 public function setCreator($creator) 128 { 129 $this->creator = $creator; 130 131 return $this; 132 } 133 134 /** 135 * Get Last Modified By. 136 * 137 * @return string 138 */ 139 public function getLastModifiedBy() 140 { 141 return $this->lastModifiedBy; 142 } 143 144 /** 145 * Set Last Modified By. 146 * 147 * @param string $pValue 148 * 149 * @return $this 150 */ 151 public function setLastModifiedBy($pValue) 152 { 153 $this->lastModifiedBy = $pValue; 154 155 return $this; 156 } 157 158 /** 159 * Get Created. 160 * 161 * @return int 162 */ 163 public function getCreated() 164 { 165 return $this->created; 166 } 167 168 /** 169 * Set Created. 170 * 171 * @param int|string $time 172 * 173 * @return $this 174 */ 175 public function setCreated($time) 176 { 177 if ($time === null) { 178 $time = time(); 179 } elseif (is_string($time)) { 180 if (is_numeric($time)) { 181 $time = (int) $time; 182 } else { 183 $time = strtotime($time); 184 } 185 } 186 187 $this->created = $time; 188 189 return $this; 190 } 191 192 /** 193 * Get Modified. 194 * 195 * @return int 196 */ 197 public function getModified() 198 { 199 return $this->modified; 200 } 201 202 /** 203 * Set Modified. 204 * 205 * @param int|string $time 206 * 207 * @return $this 208 */ 209 public function setModified($time) 210 { 211 if ($time === null) { 212 $time = time(); 213 } elseif (is_string($time)) { 214 if (is_numeric($time)) { 215 $time = (int) $time; 216 } else { 217 $time = strtotime($time); 218 } 219 } 220 221 $this->modified = $time; 222 223 return $this; 224 } 225 226 /** 227 * Get Title. 228 * 229 * @return string 230 */ 231 public function getTitle() 232 { 233 return $this->title; 234 } 235 236 /** 237 * Set Title. 238 * 239 * @param string $title 240 * 241 * @return $this 242 */ 243 public function setTitle($title) 244 { 245 $this->title = $title; 246 247 return $this; 248 } 249 250 /** 251 * Get Description. 252 * 253 * @return string 254 */ 255 public function getDescription() 256 { 257 return $this->description; 258 } 259 260 /** 261 * Set Description. 262 * 263 * @param string $description 264 * 265 * @return $this 266 */ 267 public function setDescription($description) 268 { 269 $this->description = $description; 270 271 return $this; 272 } 273 274 /** 275 * Get Subject. 276 * 277 * @return string 278 */ 279 public function getSubject() 280 { 281 return $this->subject; 282 } 283 284 /** 285 * Set Subject. 286 * 287 * @param string $subject 288 * 289 * @return $this 290 */ 291 public function setSubject($subject) 292 { 293 $this->subject = $subject; 294 295 return $this; 296 } 297 298 /** 299 * Get Keywords. 300 * 301 * @return string 302 */ 303 public function getKeywords() 304 { 305 return $this->keywords; 306 } 307 308 /** 309 * Set Keywords. 310 * 311 * @param string $keywords 312 * 313 * @return $this 314 */ 315 public function setKeywords($keywords) 316 { 317 $this->keywords = $keywords; 318 319 return $this; 320 } 321 322 /** 323 * Get Category. 324 * 325 * @return string 326 */ 327 public function getCategory() 328 { 329 return $this->category; 330 } 331 332 /** 333 * Set Category. 334 * 335 * @param string $category 336 * 337 * @return $this 338 */ 339 public function setCategory($category) 340 { 341 $this->category = $category; 342 343 return $this; 344 } 345 346 /** 347 * Get Company. 348 * 349 * @return string 350 */ 351 public function getCompany() 352 { 353 return $this->company; 354 } 355 356 /** 357 * Set Company. 358 * 359 * @param string $company 360 * 361 * @return $this 362 */ 363 public function setCompany($company) 364 { 365 $this->company = $company; 366 367 return $this; 368 } 369 370 /** 371 * Get Manager. 372 * 373 * @return string 374 */ 375 public function getManager() 376 { 377 return $this->manager; 378 } 379 380 /** 381 * Set Manager. 382 * 383 * @param string $manager 384 * 385 * @return $this 386 */ 387 public function setManager($manager) 388 { 389 $this->manager = $manager; 390 391 return $this; 392 } 393 394 /** 395 * Get a List of Custom Property Names. 396 * 397 * @return array of string 398 */ 399 public function getCustomProperties() 400 { 401 return array_keys($this->customProperties); 402 } 403 404 /** 405 * Check if a Custom Property is defined. 406 * 407 * @param string $propertyName 408 * 409 * @return bool 410 */ 411 public function isCustomPropertySet($propertyName) 412 { 413 return isset($this->customProperties[$propertyName]); 414 } 415 416 /** 417 * Get a Custom Property Value. 418 * 419 * @param string $propertyName 420 * 421 * @return mixed 422 */ 423 public function getCustomPropertyValue($propertyName) 424 { 425 if (isset($this->customProperties[$propertyName])) { 426 return $this->customProperties[$propertyName]['value']; 427 } 428 } 429 430 /** 431 * Get a Custom Property Type. 432 * 433 * @param string $propertyName 434 * 435 * @return string 436 */ 437 public function getCustomPropertyType($propertyName) 438 { 439 if (isset($this->customProperties[$propertyName])) { 440 return $this->customProperties[$propertyName]['type']; 441 } 442 } 443 444 /** 445 * Set a Custom Property. 446 * 447 * @param string $propertyName 448 * @param mixed $propertyValue 449 * @param string $propertyType 450 * 'i' : Integer 451 * 'f' : Floating Point 452 * 's' : String 453 * 'd' : Date/Time 454 * 'b' : Boolean 455 * 456 * @return $this 457 */ 458 public function setCustomProperty($propertyName, $propertyValue = '', $propertyType = null) 459 { 460 if ( 461 ($propertyType === null) || (!in_array($propertyType, [self::PROPERTY_TYPE_INTEGER, 462 self::PROPERTY_TYPE_FLOAT, 463 self::PROPERTY_TYPE_STRING, 464 self::PROPERTY_TYPE_DATE, 465 self::PROPERTY_TYPE_BOOLEAN, 466 ])) 467 ) { 468 if ($propertyValue === null) { 469 $propertyType = self::PROPERTY_TYPE_STRING; 470 } elseif (is_float($propertyValue)) { 471 $propertyType = self::PROPERTY_TYPE_FLOAT; 472 } elseif (is_int($propertyValue)) { 473 $propertyType = self::PROPERTY_TYPE_INTEGER; 474 } elseif (is_bool($propertyValue)) { 475 $propertyType = self::PROPERTY_TYPE_BOOLEAN; 476 } else { 477 $propertyType = self::PROPERTY_TYPE_STRING; 478 } 479 } 480 481 $this->customProperties[$propertyName] = [ 482 'value' => $propertyValue, 483 'type' => $propertyType, 484 ]; 485 486 return $this; 487 } 488 489 /** 490 * Implement PHP __clone to create a deep clone, not just a shallow copy. 491 */ 492 public function __clone() 493 { 494 $vars = get_object_vars($this); 495 foreach ($vars as $key => $value) { 496 if (is_object($value)) { 497 $this->$key = clone $value; 498 } else { 499 $this->$key = $value; 500 } 501 } 502 } 503 504 public static function convertProperty($propertyValue, $propertyType) 505 { 506 switch ($propertyType) { 507 case 'empty': // Empty 508 return ''; 509 510 break; 511 case 'null': // Null 512 return null; 513 514 break; 515 case 'i1': // 1-Byte Signed Integer 516 case 'i2': // 2-Byte Signed Integer 517 case 'i4': // 4-Byte Signed Integer 518 case 'i8': // 8-Byte Signed Integer 519 case 'int': // Integer 520 return (int) $propertyValue; 521 522 break; 523 case 'ui1': // 1-Byte Unsigned Integer 524 case 'ui2': // 2-Byte Unsigned Integer 525 case 'ui4': // 4-Byte Unsigned Integer 526 case 'ui8': // 8-Byte Unsigned Integer 527 case 'uint': // Unsigned Integer 528 return abs((int) $propertyValue); 529 530 break; 531 case 'r4': // 4-Byte Real Number 532 case 'r8': // 8-Byte Real Number 533 case 'decimal': // Decimal 534 return (float) $propertyValue; 535 536 break; 537 case 'lpstr': // LPSTR 538 case 'lpwstr': // LPWSTR 539 case 'bstr': // Basic String 540 return $propertyValue; 541 542 break; 543 case 'date': // Date and Time 544 case 'filetime': // File Time 545 return strtotime($propertyValue); 546 547 break; 548 case 'bool': // Boolean 549 return $propertyValue == 'true'; 550 551 break; 552 case 'cy': // Currency 553 case 'error': // Error Status Code 554 case 'vector': // Vector 555 case 'array': // Array 556 case 'blob': // Binary Blob 557 case 'oblob': // Binary Blob Object 558 case 'stream': // Binary Stream 559 case 'ostream': // Binary Stream Object 560 case 'storage': // Binary Storage 561 case 'ostorage': // Binary Storage Object 562 case 'vstream': // Binary Versioned Stream 563 case 'clsid': // Class ID 564 case 'cf': // Clipboard Data 565 return $propertyValue; 566 567 break; 568 } 569 570 return $propertyValue; 571 } 572 573 public static function convertPropertyType($propertyType) 574 { 575 switch ($propertyType) { 576 case 'i1': // 1-Byte Signed Integer 577 case 'i2': // 2-Byte Signed Integer 578 case 'i4': // 4-Byte Signed Integer 579 case 'i8': // 8-Byte Signed Integer 580 case 'int': // Integer 581 case 'ui1': // 1-Byte Unsigned Integer 582 case 'ui2': // 2-Byte Unsigned Integer 583 case 'ui4': // 4-Byte Unsigned Integer 584 case 'ui8': // 8-Byte Unsigned Integer 585 case 'uint': // Unsigned Integer 586 return self::PROPERTY_TYPE_INTEGER; 587 588 break; 589 case 'r4': // 4-Byte Real Number 590 case 'r8': // 8-Byte Real Number 591 case 'decimal': // Decimal 592 return self::PROPERTY_TYPE_FLOAT; 593 594 break; 595 case 'empty': // Empty 596 case 'null': // Null 597 case 'lpstr': // LPSTR 598 case 'lpwstr': // LPWSTR 599 case 'bstr': // Basic String 600 return self::PROPERTY_TYPE_STRING; 601 602 break; 603 case 'date': // Date and Time 604 case 'filetime': // File Time 605 return self::PROPERTY_TYPE_DATE; 606 607 break; 608 case 'bool': // Boolean 609 return self::PROPERTY_TYPE_BOOLEAN; 610 611 break; 612 case 'cy': // Currency 613 case 'error': // Error Status Code 614 case 'vector': // Vector 615 case 'array': // Array 616 case 'blob': // Binary Blob 617 case 'oblob': // Binary Blob Object 618 case 'stream': // Binary Stream 619 case 'ostream': // Binary Stream Object 620 case 'storage': // Binary Storage 621 case 'ostorage': // Binary Storage Object 622 case 'vstream': // Binary Versioned Stream 623 case 'clsid': // Class ID 624 case 'cf': // Clipboard Data 625 return self::PROPERTY_TYPE_UNKNOWN; 626 627 break; 628 } 629 630 return self::PROPERTY_TYPE_UNKNOWN; 631 } 632} 633