PluginProbe
Elementor Website Builder – more than just a page builder / 3.16.0-dev1
Elementor Website Builder – more than just a page builder v3.16.0-dev1
4.3.0-beta2 4.3.0-beta1 4.2.4 4.2.3 4.2.2 4.2.1 4.2.0 4.1.5 4.2.0-beta2 4.2.0-dev2 4.2.0-beta1 4.1.4 4.1.3 4.1.2 4.1.1 4.1.0 4.1.0-beta3 4.1.0-dev3 4.0.9 4.1.0-beta2 4.1.0-dev2 4.0.8 4.1.0-beta1 4.1.0-dev1 4.0.7 All 451 releases
elementor / core / common / modules / ajax / module.php

module.php in Elementor Website Builder – more than just a page builder 3.16.0-dev1, at core/common/modules/ajax/module.php

325 lines 7.1 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 namespace Elementor\Core\Common\Modules\Ajax;
3
4 use Elementor\Core\Base\Module as BaseModule;
5 use Elementor\Core\Utils\Exceptions;
6 use Elementor\Plugin;
7 use Elementor\Utils;
8
9 if ( ! defined( 'ABSPATH' ) ) {
10 exit; // Exit if accessed directly.
11 }
12
13 /**
14 * Elementor ajax manager.
15 *
16 * Elementor ajax manager handler class is responsible for handling Elementor
17 * ajax requests, ajax responses and registering actions applied on them.
18 *
19 * @since 2.0.0
20 */
21 class Module extends BaseModule {
22
23 const NONCE_KEY = 'elementor_ajax';
24
25 /**
26 * Ajax actions.
27 *
28 * Holds all the register ajax action.
29 *
30 * @since 2.0.0
31 * @access private
32 *
33 * @var array
34 */
35 private $ajax_actions = [];
36
37 /**
38 * Ajax requests.
39 *
40 * Holds all the register ajax requests.
41 *
42 * @since 2.0.0
43 * @access private
44 *
45 * @var array
46 */
47 private $requests = [];
48
49 /**
50 * Ajax response data.
51 *
52 * Holds all the response data for all the ajax requests.
53 *
54 * @since 2.0.0
55 * @access private
56 *
57 * @var array
58 */
59 private $response_data = [];
60
61 /**
62 * Current ajax action ID.
63 *
64 * Holds all the ID for the current ajax action.
65 *
66 * @since 2.0.0
67 * @access private
68 *
69 * @var string|null
70 */
71 private $current_action_id = null;
72
73 /**
74 * Ajax manager constructor.
75 *
76 * Initializing Elementor ajax manager.
77 *
78 * @since 2.0.0
79 * @access public
80 */
81 public function __construct() {
82 add_action( 'wp_ajax_elementor_ajax', [ $this, 'handle_ajax_request' ] );
83 }
84
85 /**
86 * Get module name.
87 *
88 * Retrieve the module name.
89 *
90 * @since 1.7.0
91 * @access public
92 *
93 * @return string Module name.
94 */
95 public function get_name() {
96 return 'ajax';
97 }
98
99 /**
100 * Register ajax action.
101 *
102 * Add new actions for a specific ajax request and the callback function to
103 * be handle the response.
104 *
105 * @since 2.0.0
106 * @access public
107 *
108 * @param string $tag Ajax request name/tag.
109 * @param callable $callback The callback function.
110 */
111 public function register_ajax_action( $tag, $callback ) {
112 if ( ! did_action( 'elementor/ajax/register_actions' ) ) {
113 _doing_it_wrong( __METHOD__, esc_html( sprintf( 'Use `%s` hook to register ajax action.', 'elementor/ajax/register_actions' ) ), '2.0.0' );
114 }
115
116 $this->ajax_actions[ $tag ] = compact( 'tag', 'callback' );
117 }
118
119 /**
120 * Handle ajax request.
121 *
122 * Verify ajax nonce, and run all the registered actions for this request.
123 *
124 * Fired by `wp_ajax_elementor_ajax` action.
125 *
126 * @since 2.0.0
127 * @access public
128 */
129 public function handle_ajax_request() {
130 if ( ! $this->verify_request_nonce() ) {
131 $this->add_response_data( false, esc_html__( 'Token Expired.', 'elementor' ) )
132 ->send_error( Exceptions::UNAUTHORIZED );
133 }
134
135 $editor_post_id = 0;
136
137 if ( ! empty( $_REQUEST['editor_post_id'] ) ) {
138 $editor_post_id = absint( $_REQUEST['editor_post_id'] );
139
140 Plugin::$instance->db->switch_to_post( $editor_post_id );
141 }
142
143 /**
144 * Register ajax actions.
145 *
146 * Fires when an ajax request is received and verified.
147 *
148 * Used to register new ajax action handles.
149 *
150 * @since 2.0.0
151 *
152 * @param self $this An instance of ajax manager.
153 */
154 do_action( 'elementor/ajax/register_actions', $this );
155
156 if ( ! empty( $_REQUEST['actions'] ) ) {
157 // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized, each action should sanitize its own data.
158 $this->requests = json_decode( wp_unslash( $_REQUEST['actions'] ), true );
159 }
160
161 foreach ( $this->requests as $id => $action_data ) {
162 $this->current_action_id = $id;
163
164 if ( ! isset( $this->ajax_actions[ $action_data['action'] ] ) ) {
165 $this->add_response_data( false, esc_html__( 'Action not found.', 'elementor' ), Exceptions::BAD_REQUEST );
166
167 continue;
168 }
169
170 if ( $editor_post_id ) {
171 $action_data['data']['editor_post_id'] = $editor_post_id;
172 }
173
174 try {
175 $results = call_user_func( $this->ajax_actions[ $action_data['action'] ]['callback'], $action_data['data'], $this );
176
177 if ( false === $results ) {
178 $this->add_response_data( false );
179 } else {
180 $this->add_response_data( true, $results );
181 }
182 } catch ( \Exception $e ) {
183 $this->add_response_data( false, $e->getMessage(), $e->getCode() );
184 }
185 }
186
187 $this->current_action_id = null;
188
189 $this->send_success();
190 }
191
192 /**
193 * Get current action data.
194 *
195 * Retrieve the data for the current ajax request.
196 *
197 * @since 2.0.1
198 * @access public
199 *
200 * @return bool|mixed Ajax request data if action exist, False otherwise.
201 */
202 public function get_current_action_data() {
203 if ( ! $this->current_action_id ) {
204 return false;
205 }
206
207 return $this->requests[ $this->current_action_id ];
208 }
209
210 /**
211 * Create nonce.
212 *
213 * Creates a cryptographic token to
214 * give the user an access to Elementor ajax actions.
215 *
216 * @since 2.3.0
217 * @access public
218 *
219 * @return string The nonce token.
220 */
221 public function create_nonce() {
222 return wp_create_nonce( self::NONCE_KEY );
223 }
224
225 /**
226 * Verify request nonce.
227 *
228 * Whether the request nonce verified or not.
229 *
230 * @since 2.3.0
231 * @access public
232 *
233 * @return bool True if request nonce verified, False otherwise.
234 */
235 public function verify_request_nonce() {
236 return wp_verify_nonce( Utils::get_super_global_value( $_REQUEST, '_nonce' ), self::NONCE_KEY );
237 }
238
239 protected function get_init_settings() {
240 return [
241 'url' => admin_url( 'admin-ajax.php' ),
242 'nonce' => $this->create_nonce(),
243 ];
244 }
245
246 /**
247 * Ajax success response.
248 *
249 * Send a JSON response data back to the ajax request, indicating success.
250 *
251 * @since 2.0.0
252 * @access protected
253 */
254 private function send_success() {
255 $response = [
256 'success' => true,
257 'data' => [
258 'responses' => $this->response_data,
259 ],
260 ];
261
262 $json = wp_json_encode( $response );
263
264 while ( ob_get_status() ) {
265 ob_end_clean();
266 }
267
268 if ( function_exists( 'gzencode' ) ) {
269 $response = gzencode( $json );
270
271 header( 'Content-Type: application/json; charset=utf-8' );
272 header( 'Content-Encoding: gzip' );
273 header( 'Content-Length: ' . strlen( $response ) );
274
275 echo $response; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
276 } else {
277 echo $json; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
278 }
279
280 wp_die( '', '', [ 'response' => null ] );
281 }
282
283 /**
284 * Ajax failure response.
285 *
286 * Send a JSON response data back to the ajax request, indicating failure.
287 *
288 * @since 2.0.0
289 * @access protected
290 *
291 * @param null $code
292 */
293 private function send_error( $code = null ) {
294 wp_send_json_error( [
295 'responses' => $this->response_data,
296 ], $code );
297 }
298
299 /**
300 * Add response data.
301 *
302 * Add new response data to the array of all the ajax requests.
303 *
304 * @since 2.0.0
305 * @access protected
306 *
307 * @param bool $success True if the requests returned successfully, False
308 * otherwise.
309 * @param mixed $data Optional. Response data. Default is null.
310 *
311 * @param int $code Optional. Response code. Default is 200.
312 *
313 * @return Module An instance of ajax manager.
314 */
315 private function add_response_data( $success, $data = null, $code = 200 ) {
316 $this->response_data[ $this->current_action_id ] = [
317 'success' => $success,
318 'code' => $code,
319 'data' => $data,
320 ];
321
322 return $this;
323 }
324 }
325