PluginProbe
Elementor Website Builder – more than just a page builder / 3.5.3
Elementor Website Builder – more than just a page builder v3.5.3
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.5.3, at core/common/modules/ajax/module.php

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