balmet.com

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs

module.php (7111B)


      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 }