You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
330 lines
7.6 KiB
PHTML
330 lines
7.6 KiB
PHTML
8 months ago
|
<?php
|
||
|
/**
|
||
|
* Rest API: Layout Block
|
||
|
*
|
||
|
* @package Divi
|
||
|
*/
|
||
|
|
||
|
if ( ! defined( 'ABSPATH' ) ) {
|
||
|
exit; // Exit if accessed directly.
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Class for custom REST API endpoint for Divi Layout block.
|
||
|
*/
|
||
|
class ET_Api_Rest_Block_Layout {
|
||
|
|
||
|
/**
|
||
|
* Instance of `ET_Api_Rest_Block_Layout`.
|
||
|
*
|
||
|
* @var ET_Api_Rest_Block_Layout
|
||
|
*/
|
||
|
private static $_instance;
|
||
|
|
||
|
/**
|
||
|
* Constructor.
|
||
|
*
|
||
|
* ET_Api_Rest_Block_Layout constructor.
|
||
|
*/
|
||
|
public function __construct() {
|
||
|
$this->register();
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Get class instance
|
||
|
*
|
||
|
* @since 4.1.0
|
||
|
*
|
||
|
* @return object class instance
|
||
|
*/
|
||
|
public static function instance() {
|
||
|
if ( null === self::$_instance ) {
|
||
|
self::$_instance = new self();
|
||
|
}
|
||
|
|
||
|
return self::$_instance;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Register callback for Layout block REST API
|
||
|
*
|
||
|
* @since 4.1.0
|
||
|
*/
|
||
|
public function register() {
|
||
|
add_action( 'rest_api_init', array( $this, 'register_routes' ) );
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Register REST API routes for Layout block
|
||
|
*
|
||
|
* @since 4.1.0
|
||
|
*/
|
||
|
public function register_routes() {
|
||
|
register_rest_route(
|
||
|
'divi/v1',
|
||
|
'get_layout_content',
|
||
|
array(
|
||
|
'methods' => 'POST',
|
||
|
'callback' => array( $this, 'get_layout_content_callback' ),
|
||
|
'args' => array(
|
||
|
'id' => array(
|
||
|
// using intval directly doesn't work, hence the custom callback.
|
||
|
'sanitize_callback' => array( $this, 'sanitize_int' ),
|
||
|
'validation_callback' => 'is_numeric',
|
||
|
),
|
||
|
'nonce' => array(
|
||
|
'sanitize_callback' => 'sanitize_text_field',
|
||
|
),
|
||
|
),
|
||
|
'permission_callback' => array( $this, 'rest_api_layout_block_permission' ),
|
||
|
)
|
||
|
);
|
||
|
|
||
|
register_rest_route(
|
||
|
'divi/v1',
|
||
|
'block/layout/builder_edit_data',
|
||
|
array(
|
||
|
'methods' => 'POST',
|
||
|
'callback' => array( $this, 'process_builder_edit_data' ),
|
||
|
'args' => array(
|
||
|
'action' => array(
|
||
|
'sanitize_callback' => array( $this, 'sanitize_action' ), // update|delete|get.
|
||
|
'validation_callback' => array( $this, 'validate_action' ),
|
||
|
),
|
||
|
'postId' => array(
|
||
|
'sanitize_callback' => array( $this, 'sanitize_int' ),
|
||
|
'validation_callback' => 'is_numeric',
|
||
|
),
|
||
|
'blockId' => array(
|
||
|
'sanitize_callback' => 'sanitize_title',
|
||
|
),
|
||
|
'layoutContent' => array(
|
||
|
'sanitize_callback' => 'wp_kses_post',
|
||
|
),
|
||
|
'nonce' => array(
|
||
|
'sanitize_callback' => 'sanitize_text_field',
|
||
|
),
|
||
|
),
|
||
|
'permission_callback' => array( $this, 'rest_api_layout_block_permission' ),
|
||
|
)
|
||
|
);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Get layout content based on given post ID
|
||
|
*
|
||
|
* @since 4.1.0
|
||
|
*
|
||
|
* @param WP_REST_Request $request Full details about the request.
|
||
|
*
|
||
|
* @return string|WP_Error
|
||
|
*/
|
||
|
public function get_layout_content_callback( WP_REST_Request $request ) {
|
||
|
$post_id = $request->get_param( 'id' );
|
||
|
$nonce = $request->get_param( 'nonce' );
|
||
|
|
||
|
// Action nonce check. REST API actually has checked for nonce at cookie sent on every
|
||
|
// request and performed capability-based check. This check perform action-based nonce
|
||
|
// check to strengthen the security
|
||
|
// @see https://developer.wordpress.org/rest-api/using-the-rest-api/authentication/.
|
||
|
if ( ! wp_verify_nonce( $nonce, 'et_rest_get_layout_content' ) ) {
|
||
|
return new WP_Error(
|
||
|
'invalid_nonce',
|
||
|
esc_html__( 'Invalid nonce', 'et_builder' ),
|
||
|
array(
|
||
|
'status' => 400,
|
||
|
)
|
||
|
);
|
||
|
}
|
||
|
|
||
|
// request has to have id param.
|
||
|
if ( ! $post_id ) {
|
||
|
return new WP_Error(
|
||
|
'no_layout_id',
|
||
|
esc_html__( 'No layout id found', 'et_builder' ),
|
||
|
array(
|
||
|
'status' => 400,
|
||
|
)
|
||
|
);
|
||
|
}
|
||
|
|
||
|
$post = get_post( $post_id );
|
||
|
|
||
|
if ( ! isset( $post->post_content ) || ! $post->post_content ) {
|
||
|
return new WP_Error(
|
||
|
'no_layout_found',
|
||
|
esc_html__( 'No valid layout content found.', 'et_builder' ),
|
||
|
array(
|
||
|
'status' => 404,
|
||
|
)
|
||
|
);
|
||
|
}
|
||
|
|
||
|
return $post->post_content;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Process /block/layout/builder_edit_data route request
|
||
|
*
|
||
|
* @param WP_Rest_Request $request Request to prepare items for.
|
||
|
*
|
||
|
* @return string|WP_Error
|
||
|
* @since 4.1.0
|
||
|
*/
|
||
|
public function process_builder_edit_data( WP_Rest_Request $request ) {
|
||
|
$post_id = $request->get_param( 'postId' );
|
||
|
$block_id = $request->get_param( 'blockId' );
|
||
|
$nonce = $request->get_param( 'nonce' );
|
||
|
|
||
|
// No post ID.
|
||
|
if ( empty( $post_id ) ) {
|
||
|
return new WP_Error(
|
||
|
'no_post_id',
|
||
|
esc_html__( 'No post id', 'et_builder' ),
|
||
|
array(
|
||
|
'status' => 400,
|
||
|
)
|
||
|
);
|
||
|
}
|
||
|
|
||
|
// No block ID.
|
||
|
if ( empty( $block_id ) ) {
|
||
|
return new WP_Error(
|
||
|
'no_block_id',
|
||
|
esc_html__( 'No block id', 'et_builder' ),
|
||
|
array(
|
||
|
'status' => 400,
|
||
|
)
|
||
|
);
|
||
|
}
|
||
|
|
||
|
// Action nonce check. REST API actually has checked for nonce at cookie sent on every
|
||
|
// request and performed capability-based check. This check perform action-based nonce
|
||
|
// check to strengthen the security
|
||
|
// @see https://developer.wordpress.org/rest-api/using-the-rest-api/authentication/.
|
||
|
if ( ! wp_verify_nonce( $nonce, 'et_rest_process_builder_edit_data' ) ) {
|
||
|
return new WP_Error(
|
||
|
'invalid_nonce',
|
||
|
esc_html__( 'Invalid nonce', 'et_builder' ),
|
||
|
array(
|
||
|
'status' => 400,
|
||
|
)
|
||
|
);
|
||
|
}
|
||
|
|
||
|
$result = '';
|
||
|
$post_meta_key = "_et_block_layout_preview_{$block_id}";
|
||
|
|
||
|
switch ( $request->get_param( 'action' ) ) {
|
||
|
case 'get':
|
||
|
$result = get_post_meta( $post_id, $post_meta_key, true );
|
||
|
break;
|
||
|
case 'update':
|
||
|
$layout_content = $request->get_param( 'layoutContent' );
|
||
|
|
||
|
// No layout content.
|
||
|
if ( empty( $layout_content ) ) {
|
||
|
return new WP_Error(
|
||
|
'no_layout_content',
|
||
|
esc_html__( 'No layout content', 'et_builder' ),
|
||
|
array(
|
||
|
'status' => 400,
|
||
|
)
|
||
|
);
|
||
|
}
|
||
|
|
||
|
$saved_layout_content = get_post_meta( $post_id, $post_meta_key, true );
|
||
|
|
||
|
if ( ! empty( $saved_layout_content ) && $saved_layout_content === $layout_content ) {
|
||
|
// If for some reason layout exist and identical to the one being sent, return
|
||
|
// true because update_post_meta() returns false if it updates the meta key and
|
||
|
// the value doesn't change.
|
||
|
$result = true;
|
||
|
} else {
|
||
|
// Otherwise, attempt to save post meta and returns how it goes.
|
||
|
$result = update_post_meta(
|
||
|
$post_id,
|
||
|
$post_meta_key,
|
||
|
$layout_content
|
||
|
);
|
||
|
}
|
||
|
|
||
|
break;
|
||
|
case 'delete':
|
||
|
$result = delete_post_meta( $post_id, $post_meta_key );
|
||
|
break;
|
||
|
default:
|
||
|
return new WP_Error(
|
||
|
'no_valid_action',
|
||
|
esc_html__( 'No valid action found', 'et_builder' ),
|
||
|
array(
|
||
|
'status' => 400,
|
||
|
)
|
||
|
);
|
||
|
}
|
||
|
|
||
|
return array(
|
||
|
'result' => $result,
|
||
|
);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Sanitize int value
|
||
|
*
|
||
|
* @since 4.1.0
|
||
|
*
|
||
|
* @param int|mixed $value Value.
|
||
|
*
|
||
|
* @return int
|
||
|
*/
|
||
|
public function sanitize_int( $value ) {
|
||
|
return intval( $value );
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Sanitize request "action" argument
|
||
|
*
|
||
|
* @since 4.1.0
|
||
|
*
|
||
|
* @param string $value Action value.
|
||
|
*
|
||
|
* @return string
|
||
|
*/
|
||
|
public function sanitize_action( $value ) {
|
||
|
return $this->validate_action( $value ) ? $value : '';
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Validate request "action" argument
|
||
|
*
|
||
|
* @since 4.1.0
|
||
|
*
|
||
|
* @param string $value Action value.
|
||
|
*
|
||
|
* @return bool
|
||
|
*/
|
||
|
public function validate_action( $value ) {
|
||
|
$valid_builder_edit_data_actions = array(
|
||
|
'get',
|
||
|
'update',
|
||
|
'delete',
|
||
|
);
|
||
|
|
||
|
return in_array( $value, $valid_builder_edit_data_actions, true );
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Permission callback for get layout permalink REST API endpoint
|
||
|
*
|
||
|
* @since 4.1.0
|
||
|
*
|
||
|
* @return bool
|
||
|
*/
|
||
|
public function rest_api_layout_block_permission() {
|
||
|
return current_user_can( 'edit_posts' ) && et_pb_is_allowed( 'use_visual_builder' );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Initialize ET_Api_Rest_Block_Layout.
|
||
|
ET_Api_Rest_Block_Layout::instance();
|