PluginProbe
Gutenberg / 23.5.1
Gutenberg v23.5.1
23.9.1 23.9.0 23.8.0 23.7.2 23.7.1 23.7.0 23.6.1 23.6.2 23.6.0 23.5.3 23.5.2 23.5.1 23.5.0 23.4.0 23.3.2 23.3.1 23.3.0 23.2.0 23.2.1 23.2.2 23.1.1 23.1.0 23.0.1 12.6.0 7.4.0 All 402 releases
gutenberg / lib / compat / wordpress-7.1 / class-wp-sync-save-server.php

class-wp-sync-save-server.php in Gutenberg 23.5.1, at lib/compat/wordpress-7.1/class-wp-sync-save-server.php

156 lines 4.2 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * WP_Sync_Save_Server class
4 *
5 * @package gutenberg
6 */
7
8 if ( ! class_exists( 'WP_Sync_Config' ) ) {
9 require_once __DIR__ . '/class-wp-sync-config.php';
10 }
11
12 if ( ! class_exists( 'WP_Sync_Save_Server' ) ) {
13
14 /**
15 * Core class that contains a REST server used for sync save requests.
16 *
17 * @since 7.1.0
18 * @access private
19 */
20 class WP_Sync_Save_Server {
21 /**
22 * REST API namespace.
23 *
24 * @since 7.1.0
25 * @var string
26 */
27 const REST_NAMESPACE = 'wp-sync/v1';
28
29 /**
30 * Meta key used to persist CRDT document snapshots.
31 *
32 * @since 7.1.0
33 * @var string
34 */
35 const CRDT_DOC_META_KEY = '_crdt_document';
36
37 /**
38 * Maximum length of the persisted CRDT document string.
39 *
40 * @since 7.1.0
41 * @var int
42 */
43 const MAX_DOC_LENGTH = 16 * MB_IN_BYTES;
44
45 /**
46 * Registers REST API routes.
47 *
48 * @since 7.1.0
49 */
50 public function register_routes(): void {
51 if ( isset( rest_get_server()->get_routes()[ '/' . self::REST_NAMESPACE . '/save' ] ) ) {
52 return;
53 }
54
55 register_rest_route(
56 self::REST_NAMESPACE,
57 '/save',
58 array(
59 'methods' => array( WP_REST_Server::CREATABLE ),
60 'callback' => array( $this, 'handle_request' ),
61 'permission_callback' => array( $this, 'check_permissions' ),
62 'args' => array(
63 'room' => array(
64 'required' => true,
65 'type' => 'string',
66 ),
67 'doc' => array(
68 'maxLength' => self::MAX_DOC_LENGTH,
69 'required' => true,
70 'type' => 'string',
71 ),
72 ),
73 )
74 );
75 }
76
77 /**
78 * Checks if the current user has permission to persist a CRDT document.
79 *
80 * @since 7.1.0
81 *
82 * @param WP_REST_Request $request The REST request.
83 * @return bool|WP_Error True if user has permission, otherwise WP_Error with details.
84 */
85 public function check_permissions( WP_REST_Request $request ) {
86 if ( ! current_user_can( 'edit_posts' ) ) {
87 return new WP_Error(
88 'rest_cannot_edit',
89 __( 'You do not have permission to perform this action', 'gutenberg' ),
90 array( 'status' => rest_authorization_required_code() )
91 );
92 }
93
94 $room = $request['room'];
95 $parsed_room = is_string( $room ) ? WP_Sync_Config::parse_room( $room ) : null;
96
97 if ( null === $parsed_room || ! $this->can_user_persist_crdt_doc( $parsed_room['entity_kind'], $parsed_room['entity_name'], $parsed_room['object_id'] ) ) {
98 return new WP_Error(
99 'rest_cannot_edit',
100 __( 'You do not have permission to persist this document.', 'gutenberg' ),
101 array( 'status' => rest_authorization_required_code() )
102 );
103 }
104
105 return true;
106 }
107
108 /**
109 * Persists a CRDT document snapshot for a supported room.
110 *
111 * @since 7.1.0
112 *
113 * @param WP_REST_Request $request The REST request.
114 * @return WP_REST_Response|WP_Error Response object or error.
115 */
116 public function handle_request( WP_REST_Request $request ) {
117 $room = $request['room'];
118 $parsed_room = is_string( $room ) ? WP_Sync_Config::parse_room( $room ) : null;
119
120 $post_id = WP_Sync_Config::get_crdt_doc_persistence_post_id(
121 $parsed_room['entity_kind'],
122 $parsed_room['entity_name'],
123 $parsed_room['object_id']
124 );
125
126 $doc = $request['doc'];
127
128 $updated = update_post_meta( $post_id, self::CRDT_DOC_META_KEY, $doc );
129 if ( false === $updated && get_post_meta( $post_id, self::CRDT_DOC_META_KEY, true ) !== $doc ) {
130 return new WP_Error(
131 'rest_crdt_save_failed',
132 __( 'Failed to save CRDT document.', 'gutenberg' ),
133 array( 'status' => 500 )
134 );
135 }
136
137 return array();
138 }
139
140 /**
141 * Checks if the current user can persist a CRDT document for an entity.
142 *
143 * @since 7.1.0
144 *
145 * @param string $entity_kind The entity kind.
146 * @param string $entity_name The entity name.
147 * @param string|null $object_id The entity ID.
148 * @return bool True if the user can persist the CRDT document, otherwise false.
149 */
150 private function can_user_persist_crdt_doc( string $entity_kind, string $entity_name, ?string $object_id ): bool {
151 $post_id = WP_Sync_Config::get_crdt_doc_persistence_post_id( $entity_kind, $entity_name, $object_id );
152 return null !== $post_id && current_user_can( 'edit_post', $post_id );
153 }
154 }
155 }
156