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