PluginProbe
WProofreader spell & grammar check plugin for WordPress / trunk
WProofreader spell & grammar check plugin for WordPress vtrunk
3.2.1 3.2.2 3.2.0 trunk 1.0 1.1 2.0 2.1 2.2 2.3 2.4 2.5 2.6 2.6.1 2.6.10 2.6.2 2.6.3 2.6.4 2.6.5 2.6.6 2.6.7 2.6.8 2.6.9 2.7.0 2.7.1 All 28 releases
webspellchecker / includes / class-wproofreader-ajax.php

class-wproofreader-ajax.php in WProofreader spell & grammar check plugin for WordPress trunk, at includes/class-wproofreader-ajax.php

135 lines 3.8 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 if ( ! defined( 'ABSPATH' ) ) {
3 exit;
4 }
5
6 /**
7 * AJAX endpoints for the settings page.
8 */
9 class WProofreader_Ajax {
10
11 const INFO_OPTION = 'wsc_proofreader_info';
12 const INFO_TRANSIENT = 'wsc_proofreader_info_cache';
13 const INFO_TTL = DAY_IN_SECONDS;
14
15 /**
16 * AJAX handler to fetch and render language list.
17 */
18 public static function get_proofreader_info() {
19 check_ajax_referer( 'webspellchecker-proofreader', 'security' );
20
21 if ( ! current_user_can( 'manage_options' ) ) {
22 wp_send_json_error( array( 'message' => __( 'Unauthorized', 'webspellchecker' ) ), 403 );
23 }
24
25 $proofreader_info = self::parse_payload( $_POST['getInfoResult'] ?? '' );
26 if ( ! is_array( $proofreader_info ) ) {
27 wp_send_json_error( array( 'message' => __( 'Invalid payload', 'webspellchecker' ) ), 400 );
28 }
29
30 $sanitized = self::sanitize_info( $proofreader_info );
31
32 update_option( self::INFO_OPTION, $sanitized, false );
33 set_transient( self::INFO_TRANSIENT, $sanitized, self::INFO_TTL );
34
35 wp_send_json_success(
36 array(
37 'html' => self::render_language_select( $sanitized ),
38 )
39 );
40 }
41
42 /** Upper bound for the getInfo JSON payload (a language list is a few KB). */
43 const MAX_PAYLOAD_BYTES = 65536;
44
45 /**
46 * The SDK getInfo result arrives either as a JSON string or, when jQuery
47 * serializes the result object into form fields, as a nested array.
48 *
49 * @param mixed $payload Raw POST payload.
50 * @return array|null
51 */
52 private static function parse_payload( $payload ) {
53 if ( is_string( $payload ) ) {
54 $payload = wp_unslash( $payload );
55 if ( '' === $payload || strlen( $payload ) > self::MAX_PAYLOAD_BYTES ) {
56 return null;
57 }
58
59 $decoded = json_decode( $payload, true );
60
61 return ( JSON_ERROR_NONE === json_last_error() && is_array( $decoded ) ) ? $decoded : null;
62 }
63
64 if ( is_array( $payload ) ) {
65 $payload = wp_unslash( $payload );
66
67 // jQuery may submit getInfoResult as nested form fields. Measure the
68 // normalized representation so this path cannot bypass the size cap.
69 $encoded = wp_json_encode( $payload );
70 if ( false === $encoded || strlen( $encoded ) > self::MAX_PAYLOAD_BYTES ) {
71 return null;
72 }
73
74 return $payload;
75 }
76
77 return null;
78 }
79
80 /**
81 * @param array $proofreader_info Raw info.
82 * @return array
83 */
84 private static function sanitize_info( array $proofreader_info ): array {
85 $sanitized = array(
86 'langList' => array(
87 'ltr' => array(),
88 'rtl' => array(),
89 ),
90 );
91
92 if ( empty( $proofreader_info['langList'] ) || ! is_array( $proofreader_info['langList'] ) ) {
93 return $sanitized;
94 }
95
96 foreach ( array( 'ltr', 'rtl' ) as $text_direction ) {
97 if ( empty( $proofreader_info['langList'][ $text_direction ] ) || ! is_array( $proofreader_info['langList'][ $text_direction ] ) ) {
98 continue;
99 }
100
101 foreach ( $proofreader_info['langList'][ $text_direction ] as $code => $label ) {
102 $code = sanitize_text_field( (string) $code );
103 $label = sanitize_text_field( (string) $label );
104 if ( '' !== $code && '' !== $label ) {
105 $sanitized['langList'][ $text_direction ][ $code ] = $label;
106 }
107 }
108 }
109
110 return $sanitized;
111 }
112
113 /**
114 * @param array $info Sanitized proofreader info.
115 * @return string
116 */
117 private static function render_language_select( array $info ): string {
118 $current_language = WProofreader::instance()->get_language();
119 $all_languages = array_merge( $info['langList']['ltr'], $info['langList']['rtl'] );
120
121 ob_start();
122 ?>
123 <select class="regular" name="wsc_proofreader[slang]" id="wsc_proofreader[slang]">
124 <?php foreach ( $all_languages as $code => $label ) : ?>
125 <option value="<?php echo esc_attr( $code ); ?>" <?php selected( $current_language, $code ); ?>>
126 <?php echo esc_html( $label ); ?>
127 </option>
128 <?php endforeach; ?>
129 </select>
130 <?php
131
132 return (string) ob_get_clean();
133 }
134 }
135