Proyectos de Subversion Moodle

Rev

| Ultima modificación | Ver Log |

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