| @@ -30,9 +30,12 @@ | ||
| 30 | 30 | * @property string $modified The date and time when the snippet data was most recently saved to the database. |
| 31 | 31 | * @property array{string,int}|null $code_error Code error encountered when last testing snippet code. |
| 32 | 32 | * @property string|null $code_error_trace Stack trace captured when last testing snippet code. |
| 33 | 33 | * @property int $revision Revision or version number of snippet. |
| 34 | - * @property string $cloud_id Cloud ID and ownership status of snippet. | |
| 34 | + * @property int $cloud_id The cloud ID of the snippet, if applicable. | |
| 35 | + * @property bool $is_cloud_owner Whether the user is the owner of the cloud snippet, if applicable. | |
| 36 | + * @property int $created_by User ID of the snippet's original author. 0 if unknown. | |
| 37 | + * @property int $updated_by User ID of the last person to save the snippet. 0 if unknown. | |
| 35 | 38 | * |
| 36 | 39 | * @property-read int $last_active Timestamp of when the snippet was last active, if available. |
| 37 | 40 | * @property-read string $display_name The snippet name if it exists or a placeholder if it does not. |
| 38 | 41 | * @property-read string $tags_list The tags in string list format. |
| @@ -41,9 +44,11 @@ | ||
| 41 | 44 | * @property-read string $type The type of snippet. |
| 42 | 45 | * @property-read string $lang The language that the snippet code is written in. |
| 43 | 46 | * @property-read int $modified_timestamp The last modification date in Unix timestamp format. |
| 44 | 47 | * @property-read DateTime $modified_local The last modification date in the local timezone. |
| 48 | + * @property-read DateTime $modified_iso The last modification date in ISO 8601 format. | |
| 45 | 49 | * @property-read bool $is_pro Whether the snippet type is pro-only. |
| 50 | + * @property-read string $cloud_id_owner Cloud ownership information as a single value, if applicable. | |
| 46 | 51 | */ |
| 47 | 52 | class Snippet extends Model { |
| 48 | 53 | |
| 49 | 54 | /** |
| @@ -61,26 +66,29 @@ | ||
| 61 | 66 | * |
| 62 | 67 | * @var array<string, mixed> |
| 63 | 68 | */ |
| 64 | 69 | protected static array $default_values = [ |
| 65 | - 'id' => 0, | |
| 66 | - 'name' => '', | |
| 67 | - 'desc' => '', | |
| 68 | - 'code' => '', | |
| 69 | - 'tags' => [], | |
| 70 | - 'scope' => 'global', | |
| 71 | - 'condition_id' => 0, | |
| 72 | - 'active' => false, | |
| 73 | - 'trashed' => false, | |
| 74 | - 'locked' => false, | |
| 75 | - 'priority' => 10, | |
| 76 | - 'network' => null, | |
| 77 | - 'shared_network' => null, | |
| 78 | - 'modified' => null, | |
| 79 | - 'code_error' => null, | |
| 70 | + 'id' => 0, | |
| 71 | + 'name' => '', | |
| 72 | + 'desc' => '', | |
| 73 | + 'code' => '', | |
| 74 | + 'tags' => [], | |
| 75 | + 'scope' => 'global', | |
| 76 | + 'condition_id' => 0, | |
| 77 | + 'active' => false, | |
| 78 | + 'trashed' => false, | |
| 79 | + 'locked' => false, | |
| 80 | + 'priority' => 10, | |
| 81 | + 'network' => null, | |
| 82 | + 'shared_network' => null, | |
| 83 | + 'modified' => null, | |
| 84 | + 'code_error' => null, | |
| 80 | 85 | 'code_error_trace' => null, |
| 81 | - 'revision' => 1, | |
| 82 | - 'cloud_id' => '', | |
| 86 | + 'revision' => 1, | |
| 87 | + 'cloud_id' => 0, | |
| 88 | + 'is_cloud_owner' => false, | |
| 89 | + 'created_by' => 0, | |
| 90 | + 'updated_by' => 0, | |
| 83 | 91 | ]; |
| 84 | 92 | |
| 85 | 93 | /** |
| 86 | 94 | * Field name aliases. |
| @@ -105,8 +113,12 @@ | ||
| 105 | 113 | switch ( $field ) { |
| 106 | 114 | case 'id': |
| 107 | 115 | case 'priority': |
| 108 | 116 | case 'condition_id': |
| 117 | + case 'cloud_id': | |
| 118 | + case 'revision': | |
| 119 | + case 'created_by': | |
| 120 | + case 'updated_by': | |
| 109 | 121 | return absint( $value ); |
| 110 | 122 | |
| 111 | 123 | case 'tags': |
| 112 | 124 | return code_snippets_build_tags_array( $value ); |
| @@ -119,8 +131,9 @@ | ||
| 119 | 131 | |
| 120 | 132 | return 1 === intval( $value ) && ! $this->trashed && ! $this->is_condition(); |
| 121 | 133 | |
| 122 | 134 | case 'locked': |
| 135 | + case 'is_cloud_owner': | |
| 123 | 136 | return is_bool( $value ) ? $value : (bool) $value; |
| 124 | 137 | |
| 125 | 138 | default: |
| 126 | 139 | return $value; |
| @@ -165,8 +178,41 @@ | ||
| 165 | 178 | return true === $network; |
| 166 | 179 | } |
| 167 | 180 | |
| 168 | 181 | /** |
| 182 | + * Set the 'cloud_id', and possibly the 'is_cloud_owner' fields. | |
| 183 | + * | |
| 184 | + * @param string|int $cloud_id Cloud identifier, possibly with cloud ownership information attached. | |
| 185 | + * | |
| 186 | + * @return int | |
| 187 | + * | |
| 188 | + * @noinspection PhpUnused | |
| 189 | + */ | |
| 190 | + protected function prepare_cloud_id( $cloud_id ): int { | |
| 191 | + if ( is_numeric( $cloud_id ) ) { | |
| 192 | + return absint( $cloud_id ); | |
| 193 | + } | |
| 194 | + | |
| 195 | + if ( is_null( $cloud_id ) ) { | |
| 196 | + return 0; | |
| 197 | + } | |
| 198 | + | |
| 199 | + $parts = explode( '_', $cloud_id ); | |
| 200 | + | |
| 201 | + $is_cloud_owner = isset( $parts[1] ) | |
| 202 | + ? filter_var( $parts[1], FILTER_VALIDATE_BOOLEAN, FILTER_NULL_ON_FAILURE ) | |
| 203 | + : null; | |
| 204 | + | |
| 205 | + if ( ! is_null( $is_cloud_owner ) ) { | |
| 206 | + $this->is_cloud_owner = $is_cloud_owner; | |
| 207 | + } | |
| 208 | + | |
| 209 | + return isset( $parts[0] ) && is_numeric( $parts[0] ) | |
| 210 | + ? absint( $parts[0] ) | |
| 211 | + : $this->cloud_id; | |
| 212 | + } | |
| 213 | + | |
| 214 | + /** | |
| 169 | 215 | * Add a new tag |
| 170 | 216 | * |
| 171 | 217 | * @param string $tag Tag content to add to list. |
| 172 | 218 | */ |
| @@ -424,8 +470,26 @@ | ||
| 424 | 470 | return $datetime ? $datetime->getTimestamp() : 0; |
| 425 | 471 | } |
| 426 | 472 | |
| 427 | 473 | /** |
| 474 | + * Retrieve the modification date as an ISO 8601 string, including the UTC | |
| 475 | + * offset. | |
| 476 | + * | |
| 477 | + * `$modified` is stored as 'Y-m-d H:i:s' in UTC, which carries no offset, so | |
| 478 | + * anything parsing it — a browser, in particular — is free to read it as | |
| 479 | + * local time and land the snippet hours away from when it was really saved. | |
| 480 | + * This is the form to hand to clients. | |
| 481 | + * | |
| 482 | + * @return string|null ISO 8601 date, or null if no modification date is set. | |
| 483 | + * @noinspection PhpUnused | |
| 484 | + */ | |
| 485 | + protected function get_modified_iso(): ?string { | |
| 486 | + $timestamp = $this->get_modified_timestamp(); | |
| 487 | + | |
| 488 | + return $timestamp ? gmdate( 'c', $timestamp ) : null; | |
| 489 | + } | |
| 490 | + | |
| 491 | + /** | |
| 428 | 492 | * Retrieve the modification time in the local timezone. |
| 429 | 493 | * |
| 430 | 494 | * @return DateTime |
| 431 | 495 | * @noinspection PhpUnused |
| @@ -495,12 +559,28 @@ | ||
| 495 | 559 | |
| 496 | 560 | /** |
| 497 | 561 | * Determine whether the current snippet type is pro-only. |
| 498 | 562 | * |
| 499 | - * @noinspection PhpUnusedPrivateMethodInspection | |
| 563 | + * @return bool | |
| 564 | + * | |
| 565 | + * @noinspection PhpUnused | |
| 500 | 566 | */ |
| 501 | - private function get_is_pro(): bool { | |
| 567 | + protected function get_is_pro(): bool { | |
| 502 | 568 | return 'css' === $this->type || 'js' === $this->type || 'cond' === $this->type; |
| 569 | + } | |
| 570 | + | |
| 571 | + /** | |
| 572 | + * Concatonate the 'cloud_id' and 'is_cloud_owner' fields to provide a single value representing the ownership | |
| 573 | + * status of the cloud snippet, if applicable. | |
| 574 | + * | |
| 575 | + * @return string | |
| 576 | + * | |
| 577 | + * @noinspection PhpUnused | |
| 578 | + */ | |
| 579 | + protected function get_cloud_id_owner(): string { | |
| 580 | + return $this->cloud_id | |
| 581 | + ? sprintf( '%d_%d', $this->cloud_id, $this->is_cloud_owner ? '1' : '0' ) | |
| 582 | + : ''; | |
| 503 | 583 | } |
| 504 | 584 | |
| 505 | 585 | /** |
| 506 | 586 | * Increment the revision number by one. |