PluginProbe
OpenStation: Desktop Windows, Dock & Virtual Desktops for WP Admin / 1.1.13
OpenStation: Desktop Windows, Dock & Virtual Desktops for WP Admin v1.1.13
1.1.13 1.1.12 1.1.11 1.1.10 1.1.9 1.1.8 1.1.7 1.1.6 1.1.5 1.1.4 1.1.3 1.1.2 1.1.1 1.1.0 1.0.1 1.0.0 0.9.8 0.9.7 0.9.6 0.9.4 0.9.5 0.9.3 0.9.2 0.9.1 0.9.0 All 37 releases
← All changes | includes/agents/conversations.php +130 -79 0.9.8 → 1.1.13 View file →
@@ -1,7 +1,7 @@
1 1 <?php
2 2 /**
3 - * Desktop Mode — Agents: persisted chat conversations.
3 + * OpenStation — Agents: persisted chat conversations.
4 4 *
5 5 * Each conversation is one post of the private `desktop_mode_chat`
6 6 * post type: `post_author` is the human who held the conversation,
7 7 * the messages live as JSON in `post_content`, the agent's user id in
@@ -21,27 +21,35 @@
21 21 * GET /agents/conversations/:id — one conversation with messages
22 22 * PUT /agents/conversations/:id — replace messages ({messages})
23 23 * DELETE /agents/conversations/:id — delete
24 24 *
25 - * @package WPDesktopMode
25 + * @package OpenStation
26 26 */
27 27
28 28 defined( 'ABSPATH' ) || exit;
29 29
30 -/** Post type holding one conversation per post. */
31 -const DESKTOP_MODE_AGENT_CHAT_POST_TYPE = 'desktop_mode_chat';
30 +/**
31 + * Post type holding one conversation per post.
32 + *
33 + * The VALUE keeps its pre-rebrand spelling on purpose: it is a
34 + * persisted or externally-visible identifier, so renaming it would
35 + * orphan data already written by live installs (or break a live
36 + * URL). The mismatch between this constant's name and its value is
37 + * deliberate — it is NOT a half-finished rename.
38 + */
39 +const OPENSTATION_AGENT_CHAT_POST_TYPE = 'desktop_mode_chat';
32 40
33 41 /** Newest conversations kept per user — creating past the cap prunes the oldest. */
34 -const DESKTOP_MODE_AGENT_CONVERSATION_CAP = 100;
42 +const OPENSTATION_AGENT_CONVERSATION_CAP = 100;
35 43
36 44 /** Newest messages kept per conversation — updates past the cap trim the oldest. */
37 -const DESKTOP_MODE_AGENT_CONVERSATION_MESSAGE_CAP = 200;
45 +const OPENSTATION_AGENT_CONVERSATION_MESSAGE_CAP = 200;
38 46
39 47 /** Stored per-message text cap. Wider than the runner's replay cap so long answers reload intact. */
40 -const DESKTOP_MODE_AGENT_CONVERSATION_TEXT_CAP = 20000;
48 +const OPENSTATION_AGENT_CONVERSATION_TEXT_CAP = 20000;
41 49
42 50 /** Characters of the last message shown as the sidebar's second line. */
43 -const DESKTOP_MODE_AGENT_CONVERSATION_PREVIEW_CAP = 80;
51 +const OPENSTATION_AGENT_CONVERSATION_PREVIEW_CAP = 80;
44 52
45 53 /**
46 54 * Entity kinds a message attachment may reference — mirrors the
47 55 * client's `DroppedEntityKind` and the drag-trigger config enum.
@@ -47,9 +55,9 @@
47 55 * client's `DroppedEntityKind` and the drag-trigger config enum.
48 56 *
49 57 * @return string[]
50 58 */
51 -function desktop_mode_agent_conversation_attachment_kinds() {
59 +function openstation_agent_conversation_attachment_kinds() {
52 60 return array( 'post', 'page', 'media', 'user', 'comment' );
53 61 }
54 62
55 63 /**
@@ -57,11 +65,11 @@
57 65 * no front-end queries, no revisions; rows die with their author.
58 66 *
59 67 * @return void
60 68 */
61 -function desktop_mode_agent_conversations_register_post_type() {
69 +function openstation_agent_conversations_register_post_type() {
62 70 register_post_type(
63 - DESKTOP_MODE_AGENT_CHAT_POST_TYPE,
71 + OPENSTATION_AGENT_CHAT_POST_TYPE,
64 72 array(
65 73 'label' => __( 'Agent conversations', 'desktop-mode' ),
66 74 'public' => false,
67 75 'show_ui' => false,
@@ -74,9 +82,9 @@
74 82 'delete_with_user' => true,
75 83 )
76 84 );
77 85 }
78 -add_action( 'init', 'desktop_mode_agent_conversations_register_post_type', 5 );
86 +add_action( 'init', 'openstation_agent_conversations_register_post_type', 5 );
79 87
80 88 /**
81 89 * Normalize caller-supplied messages for storage.
82 90 *
@@ -92,9 +100,9 @@
92 100 *
93 101 * @param mixed $messages Incoming message rows.
94 102 * @return array<int, array<string, mixed>>
95 103 */
96 -function desktop_mode_agent_conversation_sanitize_messages( $messages ) {
104 +function openstation_agent_conversation_sanitize_messages( $messages ) {
97 105 if ( ! is_array( $messages ) ) {
98 106 return array();
99 107 }
100 108
@@ -113,9 +121,9 @@
113 121 }
114 122
115 123 $entry = array(
116 124 'role' => $role,
117 - 'text' => mb_substr( $text, 0, DESKTOP_MODE_AGENT_CONVERSATION_TEXT_CAP ),
125 + 'text' => mb_substr( $text, 0, OPENSTATION_AGENT_CONVERSATION_TEXT_CAP ),
118 126 'at' => isset( $row['at'] ) ? (int) $row['at'] : 0,
119 127 );
120 128
121 129 // Call-to-action buttons survive with the message so a reopened
@@ -120,10 +128,10 @@
120 128
121 129 // Call-to-action buttons survive with the message so a reopened
122 130 // conversation still shows them (spent ones stay disabled via
123 131 // `ctaUsed`). Reuses the runner's sanitizer — same caps.
124 - if ( isset( $row['callToActions'] ) && function_exists( 'desktop_mode_agent_sanitize_call_to_actions' ) ) {
125 - $ctas = desktop_mode_agent_sanitize_call_to_actions( $row['callToActions'] );
132 + if ( isset( $row['callToActions'] ) && function_exists( 'openstation_agent_sanitize_call_to_actions' ) ) {
133 + $ctas = openstation_agent_sanitize_call_to_actions( $row['callToActions'] );
126 134 if ( ! empty( $ctas ) ) {
127 135 $entry['callToActions'] = $ctas;
128 136 }
129 137 }
@@ -131,9 +139,9 @@
131 139 $entry['ctaUsed'] = true;
132 140 }
133 141
134 142 if ( isset( $row['attachment'] ) ) {
135 - $attachment = desktop_mode_agent_conversation_sanitize_attachment( $row['attachment'] );
143 + $attachment = openstation_agent_conversation_sanitize_attachment( $row['attachment'] );
136 144 if ( null !== $attachment ) {
137 145 $entry['attachment'] = $attachment;
138 146 }
139 147 }
@@ -158,10 +166,10 @@
158 166
159 167 $clean[] = $entry;
160 168 }
161 169
162 - if ( count( $clean ) > DESKTOP_MODE_AGENT_CONVERSATION_MESSAGE_CAP ) {
163 - $clean = array_slice( $clean, -DESKTOP_MODE_AGENT_CONVERSATION_MESSAGE_CAP );
170 + if ( count( $clean ) > OPENSTATION_AGENT_CONVERSATION_MESSAGE_CAP ) {
171 + $clean = array_slice( $clean, -OPENSTATION_AGENT_CONVERSATION_MESSAGE_CAP );
164 172 }
165 173
166 174 return $clean;
167 175 }
@@ -177,15 +185,15 @@
177 185 *
178 186 * @param mixed $raw Incoming attachment block.
179 187 * @return array<string, mixed>|null
180 188 */
181 -function desktop_mode_agent_conversation_sanitize_attachment( $raw ) {
189 +function openstation_agent_conversation_sanitize_attachment( $raw ) {
182 190 if ( ! is_array( $raw ) ) {
183 191 return null;
184 192 }
185 193 $kind = isset( $raw['kind'] ) ? sanitize_key( (string) $raw['kind'] ) : '';
186 194 $id = isset( $raw['id'] ) ? (int) $raw['id'] : 0;
187 - if ( $id <= 0 || ! in_array( $kind, desktop_mode_agent_conversation_attachment_kinds(), true ) ) {
195 + if ( $id <= 0 || ! in_array( $kind, openstation_agent_conversation_attachment_kinds(), true ) ) {
188 196 return null;
189 197 }
190 198 $title = isset( $raw['title'] ) ? trim( wp_strip_all_tags( (string) $raw['title'] ) ) : '';
191 199 return array(
@@ -200,9 +208,9 @@
200 208 *
201 209 * @param array $messages Sanitized messages.
202 210 * @return string
203 211 */
204 -function desktop_mode_agent_conversation_title( array $messages ) {
212 +function openstation_agent_conversation_title( array $messages ) {
205 213 foreach ( $messages as $row ) {
206 214 if ( 'user' === $row['role'] ) {
207 215 return wp_html_excerpt( $row['text'], 60, '…' );
208 216 }
@@ -222,9 +230,9 @@
222 230 *
223 231 * @param array $messages Sanitized messages.
224 232 * @return string
225 233 */
226 -function desktop_mode_agent_conversation_preview( array $messages ) {
234 +function openstation_agent_conversation_preview( array $messages ) {
227 235 $last = empty( $messages ) ? null : $messages[ count( $messages ) - 1 ];
228 236 if ( ! is_array( $last ) ) {
229 237 return '';
230 238 }
@@ -235,12 +243,12 @@
235 243 $text = trim( (string) preg_replace( '/\s+/u', ' ', wp_strip_all_tags( (string) $last['text'] ) ) );
236 244 if ( '' === $text ) {
237 245 return '';
238 246 }
239 - if ( mb_strlen( $text ) <= DESKTOP_MODE_AGENT_CONVERSATION_PREVIEW_CAP ) {
247 + if ( mb_strlen( $text ) <= OPENSTATION_AGENT_CONVERSATION_PREVIEW_CAP ) {
240 248 return $text;
241 249 }
242 - return '…' . mb_substr( $text, -DESKTOP_MODE_AGENT_CONVERSATION_PREVIEW_CAP );
250 + return '…' . mb_substr( $text, -OPENSTATION_AGENT_CONVERSATION_PREVIEW_CAP );
243 251 }
244 252
245 253 /**
246 254 * The conversation post for `$id` when it exists AND belongs to the
@@ -248,14 +256,14 @@
248 256 *
249 257 * @param int $id Post id.
250 258 * @return WP_Post|null
251 259 */
252 -function desktop_mode_agent_conversation_get_own( $id ) {
260 +function openstation_agent_conversation_get_own( $id ) {
253 261 $post = get_post( (int) $id );
254 - if ( ! $post || DESKTOP_MODE_AGENT_CHAT_POST_TYPE !== $post->post_type ) {
262 + if ( ! $post || OPENSTATION_AGENT_CHAT_POST_TYPE !== $post->post_type ) {
255 263 return null;
256 264 }
257 - if ( (int) $post->post_author !== get_current_user_id() ) {
265 + if ( get_current_user_id() !== (int) $post->post_author ) {
258 266 return null;
259 267 }
260 268 return $post;
261 269 }
@@ -268,9 +276,9 @@
268 276 * @param WP_Post $post Conversation post.
269 277 * @param bool $with_messages Include the decoded messages array.
270 278 * @return array<string, mixed>
271 279 */
272 -function desktop_mode_agent_conversation_prepare( WP_Post $post, $with_messages = false ) {
280 +function openstation_agent_conversation_prepare( WP_Post $post, $with_messages = false ) {
273 281 $agent_id = (int) get_post_meta( $post->ID, '_desktop_mode_agent_chat_agent_id', true );
274 282 $agent = $agent_id > 0 ? get_userdata( $agent_id ) : false;
275 283
276 284 $messages = json_decode( (string) $post->post_content, true );
@@ -282,15 +290,15 @@
282 290
283 291 $out = array(
284 292 'id' => (int) $post->ID,
285 293 'agentId' => $agent_id,
286 - 'agentName' => $agent ? $agent->display_name : __( 'Deleted agent', 'desktop-mode' ),
294 + 'agentName' => $agent ? openstation_plain_text_title( $agent->display_name ) : __( 'Deleted agent', 'desktop-mode' ),
287 295 'agentDescription' => $agent ? (string) get_user_meta( $agent_id, '_desktop_mode_agent_description', true ) : '',
288 - 'agentAvatarUrl' => function_exists( 'desktop_mode_agent_avatar_url' ) ? desktop_mode_agent_avatar_url() : '',
296 + 'agentAvatarUrl' => function_exists( 'openstation_agent_avatar_url' ) ? openstation_agent_avatar_url( $agent_id ) : '',
289 297 'title' => (string) $post->post_title,
290 298 // Second sidebar line + who spoke last, so the list can say
291 299 // where each conversation got to instead of repeating its opener.
292 - 'preview' => desktop_mode_agent_conversation_preview( $messages ),
300 + 'preview' => openstation_agent_conversation_preview( $messages ),
293 301 'lastRole' => is_array( $last ) && isset( $last['role'] ) ? (string) $last['role'] : '',
294 302 'messageCount' => count( $messages ),
295 303 'createdAt' => mysql2date( 'c', $post->post_date_gmt, false ),
296 304 'updatedAt' => mysql2date( 'c', $post->post_modified_gmt, false ),
@@ -309,9 +317,9 @@
309 317 * handler scope every read and write to the caller's rows.
310 318 *
311 319 * @return void
312 320 */
313 -function desktop_mode_agent_conversations_register_routes() {
321 +function openstation_agent_conversations_register_routes() {
314 322 register_rest_route(
315 323 'desktop-mode/v1',
316 324 '/agents/conversations',
317 325 array(
@@ -316,15 +324,15 @@
316 324 '/agents/conversations',
317 325 array(
318 326 array(
319 327 'methods' => WP_REST_Server::READABLE,
320 - 'callback' => 'desktop_mode_agents_rest_conversations_list',
321 - 'permission_callback' => 'desktop_mode_agents_rest_invoke_permission',
328 + 'callback' => 'openstation_agents_rest_conversations_list',
329 + 'permission_callback' => 'openstation_agents_rest_invoke_permission',
322 330 ),
323 331 array(
324 332 'methods' => WP_REST_Server::CREATABLE,
325 - 'callback' => 'desktop_mode_agents_rest_conversations_create',
326 - 'permission_callback' => 'desktop_mode_agents_rest_invoke_permission',
333 + 'callback' => 'openstation_agents_rest_conversations_create',
334 + 'permission_callback' => 'openstation_agents_rest_invoke_permission',
327 335 'args' => array(
328 336 'agentId' => array(
329 337 'type' => 'integer',
330 338 'required' => true,
@@ -344,15 +352,15 @@
344 352 '/agents/conversations/(?P<id>\d+)',
345 353 array(
346 354 array(
347 355 'methods' => WP_REST_Server::READABLE,
348 - 'callback' => 'desktop_mode_agents_rest_conversations_get',
349 - 'permission_callback' => 'desktop_mode_agents_rest_invoke_permission',
356 + 'callback' => 'openstation_agents_rest_conversations_get',
357 + 'permission_callback' => 'openstation_agents_rest_invoke_permission',
350 358 ),
351 359 array(
352 360 'methods' => WP_REST_Server::EDITABLE,
353 - 'callback' => 'desktop_mode_agents_rest_conversations_update',
354 - 'permission_callback' => 'desktop_mode_agents_rest_invoke_permission',
361 + 'callback' => 'openstation_agents_rest_conversations_update',
362 + 'permission_callback' => 'openstation_agents_rest_invoke_permission',
355 363 'args' => array(
356 364 'messages' => array(
357 365 'type' => 'array',
358 366 'required' => true,
@@ -360,15 +368,15 @@
360 368 ),
361 369 ),
362 370 array(
363 371 'methods' => WP_REST_Server::DELETABLE,
364 - 'callback' => 'desktop_mode_agents_rest_conversations_delete',
365 - 'permission_callback' => 'desktop_mode_agents_rest_invoke_permission',
372 + 'callback' => 'openstation_agents_rest_conversations_delete',
373 + 'permission_callback' => 'openstation_agents_rest_invoke_permission',
366 374 ),
367 375 )
368 376 );
369 377 }
370 -add_action( 'rest_api_init', 'desktop_mode_agent_conversations_register_routes' );
378 +add_action( 'rest_api_init', 'openstation_agent_conversations_register_routes' );
371 379
372 380 /**
373 381 * GET /agents/conversations — the caller's conversations, most
374 382 * recently updated first, without message bodies (the list must stay
@@ -375,15 +383,15 @@
375 383 * light; the sidebar fetches bodies on click).
376 384 *
377 385 * @return WP_REST_Response
378 386 */
379 -function desktop_mode_agents_rest_conversations_list() {
387 +function openstation_agents_rest_conversations_list() {
380 388 $posts = get_posts(
381 389 array(
382 - 'post_type' => DESKTOP_MODE_AGENT_CHAT_POST_TYPE,
390 + 'post_type' => OPENSTATION_AGENT_CHAT_POST_TYPE,
383 391 'post_status' => 'publish',
384 392 'author' => get_current_user_id(),
385 - 'numberposts' => desktop_mode_agent_conversation_cap(),
393 + 'numberposts' => openstation_agent_conversation_cap(),
386 394 'orderby' => 'modified',
387 395 'order' => 'DESC',
388 396 'suppress_filters' => false,
389 397 )
@@ -389,57 +397,98 @@
389 397 )
390 398 );
391 399
392 400 return rest_ensure_response(
393 - array_map( 'desktop_mode_agent_conversation_prepare', $posts )
401 + array_map( 'openstation_agent_conversation_prepare', $posts )
394 402 );
395 403 }
396 404
397 405 /**
406 + * Keep the save filters off a conversation's title and transcript,
407 + * the way `WP_Customize_Manager` does for changeset JSON. Hooked only
408 + * while one of the handlers below saves.
409 + *
410 + * Both are text the client paints as text, never HTML that WordPress
411 + * echoes, yet `title_save_pre` and `content_save_pre` rewrite them as
412 + * HTML. For a user without `unfiltered_html`, kses turns `&` into
413 + * `&amp;`, drops whatever sits between a `<` and a `>`, and unescapes
414 + * an attribute's quotes. On a site that balances tags, `balanceTags`
415 + * appends closing tags for every role. Those last two leave JSON that
416 + * no longer decodes.
417 + *
418 + * @param array $data Slashed, sanitized post data.
419 + * @param array $postarr Sanitized post data.
420 + * @param array $unsanitized_postarr Slashed post data as passed to `wp_insert_post()`.
421 + * @return array
422 + */
423 +function openstation_agent_conversation_preserve_text( $data, $postarr, $unsanitized_postarr ) {
424 + global $wpdb;
425 +
426 + if ( OPENSTATION_AGENT_CHAT_POST_TYPE !== $data['post_type'] ) {
427 + return $data;
428 + }
429 + foreach ( array( 'post_title', 'post_content' ) as $field ) {
430 + if ( ! isset( $unsanitized_postarr[ $field ] ) ) {
431 + continue;
432 + }
433 + $data[ $field ] = $unsanitized_postarr[ $field ];
434 + // `wp_insert_post()` has already swapped emoji for entities
435 + // where the column is utf8mb3, which rejects them and fails
436 + // the save. Redo it on the restored text.
437 + if ( in_array( $wpdb->get_col_charset( $wpdb->posts, $field ), array( 'utf8', 'utf8mb3' ), true ) ) {
438 + $data[ $field ] = wp_encode_emoji( $data[ $field ] );
439 + }
440 + }
441 + return $data;
442 +}
443 +
444 +/**
398 445 * POST /agents/conversations — create from {agentId, messages}.
399 446 *
400 447 * @param WP_REST_Request $request Request.
401 448 * @return WP_REST_Response|WP_Error
402 449 */
403 -function desktop_mode_agents_rest_conversations_create( WP_REST_Request $request ) {
450 +function openstation_agents_rest_conversations_create( WP_REST_Request $request ) {
404 451 $agent_id = (int) $request['agentId'];
405 - if ( ! function_exists( 'desktop_mode_agent_is_agent' ) || ! desktop_mode_agent_is_agent( $agent_id ) ) {
452 + if ( ! function_exists( 'openstation_agent_is_agent' ) || ! openstation_agent_is_agent( $agent_id ) ) {
406 453 return new WP_Error(
407 - 'desktop_mode_agent_not_found',
454 + 'openstation_agent_not_found',
408 455 __( 'No agent with that id exists.', 'desktop-mode' ),
409 456 array( 'status' => 404 )
410 457 );
411 458 }
412 459
413 - $messages = desktop_mode_agent_conversation_sanitize_messages( $request['messages'] );
460 + $messages = openstation_agent_conversation_sanitize_messages( $request['messages'] );
414 461 if ( empty( $messages ) ) {
415 462 return new WP_Error(
416 - 'desktop_mode_agent_conversation_empty',
463 + 'openstation_agent_conversation_empty',
417 464 __( 'A conversation needs at least one message.', 'desktop-mode' ),
418 465 array( 'status' => 400 )
419 466 );
420 467 }
421 468
469 + add_filter( 'wp_insert_post_data', 'openstation_agent_conversation_preserve_text', 5, 3 );
422 470 $post_id = wp_insert_post(
423 471 array(
424 - 'post_type' => DESKTOP_MODE_AGENT_CHAT_POST_TYPE,
472 + 'post_type' => OPENSTATION_AGENT_CHAT_POST_TYPE,
425 473 'post_status' => 'publish',
426 474 'post_author' => get_current_user_id(),
427 - 'post_title' => desktop_mode_agent_conversation_title( $messages ),
428 - // JSON survives the insert-path unslashing only when slashed.
475 + // Both survive the insert-path unslashing only when slashed.
476 + 'post_title' => wp_slash( openstation_agent_conversation_title( $messages ) ),
429 477 'post_content' => wp_slash( (string) wp_json_encode( $messages ) ),
430 478 ),
431 479 true
432 480 );
481 + remove_filter( 'wp_insert_post_data', 'openstation_agent_conversation_preserve_text', 5 );
433 482 if ( is_wp_error( $post_id ) ) {
434 483 return $post_id;
435 484 }
436 485 update_post_meta( $post_id, '_desktop_mode_agent_chat_agent_id', $agent_id );
437 486
438 - desktop_mode_agent_conversations_prune( get_current_user_id() );
487 + openstation_agent_conversations_prune( get_current_user_id() );
439 488
440 489 return rest_ensure_response(
441 - desktop_mode_agent_conversation_prepare( get_post( $post_id ), true )
490 + openstation_agent_conversation_prepare( get_post( $post_id ), true )
442 491 );
443 492 }
444 493
445 494 /**
@@ -447,15 +496,15 @@
447 496 *
448 497 * @param WP_REST_Request $request Request.
449 498 * @return WP_REST_Response|WP_Error
450 499 */
451 -function desktop_mode_agents_rest_conversations_get( WP_REST_Request $request ) {
452 - $post = desktop_mode_agent_conversation_get_own( (int) $request['id'] );
500 +function openstation_agents_rest_conversations_get( WP_REST_Request $request ) {
501 + $post = openstation_agent_conversation_get_own( (int) $request['id'] );
453 502 if ( ! $post ) {
454 - return desktop_mode_agent_conversation_not_found();
503 + return openstation_agent_conversation_not_found();
455 504 }
456 505 return rest_ensure_response(
457 - desktop_mode_agent_conversation_prepare( $post, true )
506 + openstation_agent_conversation_prepare( $post, true )
458 507 );
459 508 }
460 509
461 510 /**
@@ -465,37 +514,39 @@
465 514 *
466 515 * @param WP_REST_Request $request Request.
467 516 * @return WP_REST_Response|WP_Error
468 517 */
469 -function desktop_mode_agents_rest_conversations_update( WP_REST_Request $request ) {
470 - $post = desktop_mode_agent_conversation_get_own( (int) $request['id'] );
518 +function openstation_agents_rest_conversations_update( WP_REST_Request $request ) {
519 + $post = openstation_agent_conversation_get_own( (int) $request['id'] );
471 520 if ( ! $post ) {
472 - return desktop_mode_agent_conversation_not_found();
521 + return openstation_agent_conversation_not_found();
473 522 }
474 523
475 - $messages = desktop_mode_agent_conversation_sanitize_messages( $request['messages'] );
524 + $messages = openstation_agent_conversation_sanitize_messages( $request['messages'] );
476 525 if ( empty( $messages ) ) {
477 526 return new WP_Error(
478 - 'desktop_mode_agent_conversation_empty',
527 + 'openstation_agent_conversation_empty',
479 528 __( 'A conversation needs at least one message.', 'desktop-mode' ),
480 529 array( 'status' => 400 )
481 530 );
482 531 }
483 532
533 + add_filter( 'wp_insert_post_data', 'openstation_agent_conversation_preserve_text', 5, 3 );
484 534 $updated = wp_update_post(
485 535 array(
486 536 'ID' => $post->ID,
487 - 'post_title' => desktop_mode_agent_conversation_title( $messages ),
537 + 'post_title' => wp_slash( openstation_agent_conversation_title( $messages ) ),
488 538 'post_content' => wp_slash( (string) wp_json_encode( $messages ) ),
489 539 ),
490 540 true
491 541 );
542 + remove_filter( 'wp_insert_post_data', 'openstation_agent_conversation_preserve_text', 5 );
492 543 if ( is_wp_error( $updated ) ) {
493 544 return $updated;
494 545 }
495 546
496 547 return rest_ensure_response(
497 - desktop_mode_agent_conversation_prepare( get_post( $post->ID ), true )
548 + openstation_agent_conversation_prepare( get_post( $post->ID ), true )
498 549 );
499 550 }
500 551
501 552 /**
@@ -503,12 +554,12 @@
503 554 *
504 555 * @param WP_REST_Request $request Request.
505 556 * @return WP_REST_Response|WP_Error
506 557 */
507 -function desktop_mode_agents_rest_conversations_delete( WP_REST_Request $request ) {
508 - $post = desktop_mode_agent_conversation_get_own( (int) $request['id'] );
558 +function openstation_agents_rest_conversations_delete( WP_REST_Request $request ) {
559 + $post = openstation_agent_conversation_get_own( (int) $request['id'] );
509 560 if ( ! $post ) {
510 - return desktop_mode_agent_conversation_not_found();
561 + return openstation_agent_conversation_not_found();
511 562 }
512 563 wp_delete_post( $post->ID, true );
513 564 return rest_ensure_response( array( 'deleted' => true ) );
514 565 }
@@ -518,11 +569,11 @@
518 569 * "does not exist" and "not yours" so ids can't be probed.
519 570 *
520 571 * @return WP_Error
521 572 */
522 -function desktop_mode_agent_conversation_not_found() {
573 +function openstation_agent_conversation_not_found() {
523 574 return new WP_Error(
524 - 'desktop_mode_agent_conversation_not_found',
575 + 'openstation_agent_conversation_not_found',
525 576 __( 'No conversation with that id exists.', 'desktop-mode' ),
526 577 array( 'status' => 404 )
527 578 );
528 579 }
@@ -531,9 +582,9 @@
531 582 * The effective per-user conversation cap.
532 583 *
533 584 * @return int
534 585 */
535 -function desktop_mode_agent_conversation_cap() {
586 +function openstation_agent_conversation_cap() {
536 587 /**
537 588 * Filters how many conversations are kept per user. Creating past
538 589 * the cap prunes the least recently updated rows.
539 590 *
@@ -538,9 +589,9 @@
538 589 * the cap prunes the least recently updated rows.
539 590 *
540 591 * @param int $cap Maximum stored conversations per user.
541 592 */
542 - return max( 1, (int) apply_filters( 'desktop_mode_agent_conversation_cap', DESKTOP_MODE_AGENT_CONVERSATION_CAP ) );
593 + return max( 1, (int) apply_filters( 'openstation_agent_conversation_cap', OPENSTATION_AGENT_CONVERSATION_CAP ) );
543 594 }
544 595
545 596 /**
546 597 * Drop the user's oldest conversations beyond the cap.
@@ -547,13 +598,13 @@
547 598 *
548 599 * @param int $user_id Owner.
549 600 * @return void
550 601 */
551 -function desktop_mode_agent_conversations_prune( $user_id ) {
552 - $cap = desktop_mode_agent_conversation_cap();
602 +function openstation_agent_conversations_prune( $user_id ) {
603 + $cap = openstation_agent_conversation_cap();
553 604 $posts = get_posts(
554 605 array(
555 - 'post_type' => DESKTOP_MODE_AGENT_CHAT_POST_TYPE,
606 + 'post_type' => OPENSTATION_AGENT_CHAT_POST_TYPE,
556 607 'post_status' => 'publish',
557 608 'author' => (int) $user_id,
558 609 // One page past the cap is plenty — pruning runs on every create.
559 610 'numberposts' => $cap + 10,