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 Properties 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 Properties 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 Properties 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 Properties 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 Properties 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 Properties 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 Properties 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 Properties 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 Properties 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 Properties 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 Properties 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 string 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 Properties 457 */ 458 public function setCustomProperty($propertyName, $propertyValue = '', $propertyType = null) 459 { 460 if (($propertyType === null) || (!in_array($propertyType, [self::PROPERTY_TYPE_INTEGER, 461 self::PROPERTY_TYPE_FLOAT, 462 self::PROPERTY_TYPE_STRING, 463 self::PROPERTY_TYPE_DATE, 464 self::PROPERTY_TYPE_BOOLEAN, ]))) { 465 if ($propertyValue === null) { 466 $propertyType = self::PROPERTY_TYPE_STRING; 467 } elseif (is_float($propertyValue)) { 468 $propertyType = self::PROPERTY_TYPE_FLOAT; 469 } elseif (is_int($propertyValue)) { 470 $propertyType = self::PROPERTY_TYPE_INTEGER; 471 } elseif (is_bool($propertyValue)) { 472 $propertyType = self::PROPERTY_TYPE_BOOLEAN; 473 } else { 474 $propertyType = self::PROPERTY_TYPE_STRING; 475 } 476 } 477 478 $this->customProperties[$propertyName] = [ 479 'value' => $propertyValue, 480 'type' => $propertyType, 481 ]; 482 483 return $this; 484 } 485 486 /** 487 * Implement PHP __clone to create a deep clone, not just a shallow copy. 488 */ 489 public function __clone() 490 { 491 $vars = get_object_vars($this); 492 foreach ($vars as $key => $value) { 493 if (is_object($value)) { 494 $this->$key = clone $value; 495 } else { 496 $this->$key = $value; 497 } 498 } 499 } 500 501 public static function convertProperty($propertyValue, $propertyType) 502 { 503 switch ($propertyType) { 504 case 'empty': // Empty 505 return ''; 506 507 break; 508 case 'null': // Null 509 return null; 510 511 break; 512 case 'i1': // 1-Byte Signed Integer 513 case 'i2': // 2-Byte Signed Integer 514 case 'i4': // 4-Byte Signed Integer 515 case 'i8': // 8-Byte Signed Integer 516 case 'int': // Integer 517 return (int) $propertyValue; 518 519 break; 520 case 'ui1': // 1-Byte Unsigned Integer 521 case 'ui2': // 2-Byte Unsigned Integer 522 case 'ui4': // 4-Byte Unsigned Integer 523 case 'ui8': // 8-Byte Unsigned Integer 524 case 'uint': // Unsigned Integer 525 return abs((int) $propertyValue); 526 527 break; 528 case 'r4': // 4-Byte Real Number 529 case 'r8': // 8-Byte Real Number 530 case 'decimal': // Decimal 531 return (float) $propertyValue; 532 533 break; 534 case 'lpstr': // LPSTR 535 case 'lpwstr': // LPWSTR 536 case 'bstr': // Basic String 537 return $propertyValue; 538 539 break; 540 case 'date': // Date and Time 541 case 'filetime': // File Time 542 return strtotime($propertyValue); 543 544 break; 545 case 'bool': // Boolean 546 return $propertyValue == 'true'; 547 548 break; 549 case 'cy': // Currency 550 case 'error': // Error Status Code 551 case 'vector': // Vector 552 case 'array': // Array 553 case 'blob': // Binary Blob 554 case 'oblob': // Binary Blob Object 555 case 'stream': // Binary Stream 556 case 'ostream': // Binary Stream Object 557 case 'storage': // Binary Storage 558 case 'ostorage': // Binary Storage Object 559 case 'vstream': // Binary Versioned Stream 560 case 'clsid': // Class ID 561 case 'cf': // Clipboard Data 562 return $propertyValue; 563 564 break; 565 } 566 567 return $propertyValue; 568 } 569 570 public static function convertPropertyType($propertyType) 571 { 572 switch ($propertyType) { 573 case 'i1': // 1-Byte Signed Integer 574 case 'i2': // 2-Byte Signed Integer 575 case 'i4': // 4-Byte Signed Integer 576 case 'i8': // 8-Byte Signed Integer 577 case 'int': // Integer 578 case 'ui1': // 1-Byte Unsigned Integer 579 case 'ui2': // 2-Byte Unsigned Integer 580 case 'ui4': // 4-Byte Unsigned Integer 581 case 'ui8': // 8-Byte Unsigned Integer 582 case 'uint': // Unsigned Integer 583 return self::PROPERTY_TYPE_INTEGER; 584 585 break; 586 case 'r4': // 4-Byte Real Number 587 case 'r8': // 8-Byte Real Number 588 case 'decimal': // Decimal 589 return self::PROPERTY_TYPE_FLOAT; 590 591 break; 592 case 'empty': // Empty 593 case 'null': // Null 594 case 'lpstr': // LPSTR 595 case 'lpwstr': // LPWSTR 596 case 'bstr': // Basic String 597 return self::PROPERTY_TYPE_STRING; 598 599 break; 600 case 'date': // Date and Time 601 case 'filetime': // File Time 602 return self::PROPERTY_TYPE_DATE; 603 604 break; 605 case 'bool': // Boolean 606 return self::PROPERTY_TYPE_BOOLEAN; 607 608 break; 609 case 'cy': // Currency 610 case 'error': // Error Status Code 611 case 'vector': // Vector 612 case 'array': // Array 613 case 'blob': // Binary Blob 614 case 'oblob': // Binary Blob Object 615 case 'stream': // Binary Stream 616 case 'ostream': // Binary Stream Object 617 case 'storage': // Binary Storage 618 case 'ostorage': // Binary Storage Object 619 case 'vstream': // Binary Versioned Stream 620 case 'clsid': // Class ID 621 case 'cf': // Clipboard Data 622 return self::PROPERTY_TYPE_UNKNOWN; 623 624 break; 625 } 626 627 return self::PROPERTY_TYPE_UNKNOWN; 628 } 629} 630