plugin_id = 'gutenberg/gutenberg.php';
if ( function_exists( 'gutenberg_can_edit_post' ) ) {
$this->init_hooks();
}
}
/**
* Filter on map_meta_cap.
*
* @param array $caps Capabilities.
* @param string $cap Capability to check.
* @param string $user_id User ID.
* @param array $args Additional args.
*
* @access public.
* @return void
*/
public function map_meta_cap( $caps, $cap, $user_id, $args ) {
// This only needs to run once,
remove_filter( 'map_meta_cap', array( $this, 'map_meta_cap' ), 10 );
if (
// GB checks for 'edit_post' so do nothing in all other cases
'edit_post' !== $cap ||
// Ignore the case where Divi wasn't used to edit the post
! et_pb_is_pagebuilder_used( $args[0] )
) {
return $caps;
}
// We need to add `do_not_allow` for superadmins
$caps = array( 'do_not_allow' );
return $caps;
}//end map_meta_cap()
/**
* Filter used to disable GB for certain post types.
*
* @param bool $can_edit
* @param string $post_type
*
* @access public.
* @return void
*/
public function gutenberg_can_edit_post_type( $can_edit, $post_type ) {
// The tricky part here is that GB doesn't pass the post ID to this filter but only its type
// but we need the ID to determine whether the post has been edited with Divi.
// Since GB uses `current_user_can( 'edit_post', $post->ID )` right after call this filter,
// We hook into `map_meta_cap` (which gets passed the ID) and do our checks there
add_filter( 'map_meta_cap', array( $this, 'map_meta_cap' ), 10, 4 );
return $can_edit;
}// end gutenberg_can_edit_post_type()
/**
* Enqueue our GB compatibility bundle.
*
* @access public.
* @return void
*/
public function enqueue_block_editor_assets() {
et_fb_enqueue_bundle( 'et-builder-gutenberg', 'gutenberg.js', array( 'jquery' ) );
et_fb_enqueue_bundle( 'et-builder-gutenberg', 'gutenberg.css', array() );
$res = et_pb_is_pagebuilder_used();
// Set helpers needed by our own Gutenberg bundle.
wp_localize_script( 'et-builder-gutenberg', 'et_builder_gutenberg', array(
'helpers' => array(
'postID' => get_the_ID(),
'postType' => get_post_type(),
'vbUrl' => add_query_arg( 'et_fb', true, et_fb_prepare_ssl_link( get_the_permalink() ) ),
'builderUsed' => et_pb_is_pagebuilder_used(),
'scriptDebug' => defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG,
'i18n' => array(
'placeholder' => array(
'block' => array(
'title' => esc_html__( 'Divi Builder', 'et_builder' ),
'description' => esc_html__( 'The Divi Builder is activated on this page. To edit your page using the builder, click the Launch The Divi Builder button.', 'et_builder' ),
),
'render' => array(
'title' => array(
'new' => esc_html__( 'Build Your Page on the Front-End Using Divi', 'et_builder' ),
'old' => esc_html__( 'The Divi Builder Is Enabled', 'et_builder' ),
),
'divi' => array(
'new' => esc_html__( 'Use Divi Builder', 'et_builder' ),
'old' => esc_html__( 'Launch The Divi Builder', 'et_builder' ),
),
'default' => esc_html__( 'Use Default Editor', 'et_builder' ),
),
),
),
),
));
}// end enqueue_block_editor_assets()
/**
* Add new Divi page
*
* @access public
* @return void
*/
public function add_new_button() {
global $typenow;
if ( ! gutenberg_can_edit_post_type( $typenow ) ) {
return;
}
$edit = 'post-new.php';
$edit .= 'post' !== $typenow ? "?post_type=$typenow" : '';
// Create a nonce to auto activate VB on a new Auto Draft
$url = add_query_arg(
array(
'et_fb_new_vb_nonce' => wp_create_nonce( 'et_fb_new_vb_nonce' ),
),
admin_url( $edit )
);
$button = sprintf( '%s', esc_url( $url ), 'Divi' );
?>
$post->ID,
'post_status' => 'draft',
));
// Add VB activation nonce
$url = add_query_arg(
array(
'et_fb_activation_nonce' => wp_create_nonce( 'et_fb_activation_nonce_' . $post->ID ),
),
et_fb_prepare_ssl_link( get_permalink( $post ) )
);
// Set post meta to `off` or else `et_builder_set_content_activation` won't work...
update_post_meta( $post->ID, '_et_pb_use_builder', 'off' );
wp_redirect( $url );
exit();
}//end auto_draft()
/**
* Add 'Edit With Divi Editor' links
*
* @param array $actions Currently defined actions for the row.
* @param object $post Current post object.
*
* @access public.
* @return void
*/
public function add_edit_link( $actions, $post ) {
// Maybe change this with et_fb_current_user_can_save or equivalent
if ( ! gutenberg_can_edit_post( $post ) ) {
return $actions;
}
$post_id = $post->ID;
$is_divi_library = 'et_pb_layout' === get_post_type( $post_id );
$edit_url = $is_divi_library ? get_edit_post_link( $post_id, 'raw' ) : get_permalink( $post_id );
if ( et_pb_is_pagebuilder_used( $post_id ) ) {
$edit_url = add_query_arg( 'et_fb', '1', et_fb_prepare_ssl_link( $edit_url ) );
} else {
$edit_url = add_query_arg(
array(
'et_fb_activation_nonce' => wp_create_nonce( 'et_fb_activation_nonce_' . $post_id ),
),
$edit_url
);
}
$edit_action = array(
'divi' => sprintf(
'%s',
esc_url( $edit_url ),
esc_attr( sprintf(
__( 'Edit “%s” in Divi', 'et-builder' ),
_draft_or_post_title( $post->ID )
) ),
esc_html__( 'Edit With Divi Builder', 'et-builder' )
),
);
$actions = array_merge( $actions, $edit_action );
// I'm leaving this here in case we wanna change item position.
// $edit_offset = array_search( 'edit', array_keys( $actions ), true );
// $actions = array_merge(
// array_slice( $actions, 0, $edit_offset + 1 ),
// $edit_action,
// array_slice( $actions, $edit_offset + 1 )
// );
return $actions;
}//end add_edit_link()
/**
* Add filters needed to show our extra row action.
*
* @access public.
* @return void
*/
public function add_edit_link_filters() {
// For hierarchical post types.
add_filter( 'page_row_actions', array( $this, 'add_edit_link' ), 10, 2 );
// For non-hierarchical post types.
add_filter( 'post_row_actions', array( $this, 'add_edit_link' ), 10, 2 );
}// add_edit_link_filters()
/**
* Add 'Divi' to post states when builder is enabled for it.
*
* @param array $post_states Existing post states.
* @param object $post Current post object.
*
* @access public.
* @return array
*/
public function display_post_states( $post_states, $post ) {
if ( et_pb_is_pagebuilder_used( $post->ID ) ) {
// Remove Gutenberg if existing
$key = array_search( 'Gutenberg', $post_states );
if ( false !== $key ) {
unset( $post_states[ $key ] );
}
// GB devs didn't allow this to be translated so why should we ?
$post_states[] = 'Divi';
}
return $post_states;
}//end display_post_states()
/**
* Alter update_post_metadata return value from during a REST API update
* when meta value isn't changed.
*
* @param mixed $result Previous result.
* @param int $object_id Post ID.
* @param string $meta_key Meta key.
* @param mixed $meta_value Meta value.
*
* @access public.
* @return mixed
*/
public function update_post_metadata( $result, $object_id, $meta_key, $meta_value ) {
if ( ! in_array( $meta_key, array( '_et_pb_use_builder', '_et_pb_old_content' ) ) ) {
// Only act if it's one of our metas
return $result;
}
if ( $meta_value === get_metadata( 'post', $object_id, $meta_key, true ) ) {
// Return true instead of false so silly WP REST API call won't die on us....
return true;
}
return $result;
}//end update_post_metadata()
/**
* Remove empty Divi GB placeholder when processing shortcode.
*
* @param string $post_content Raw post content (shortcode).
*
* @access public.
* @return string
*/
public function et_fb_load_raw_post_content( $post_content ) {
// Replace empty placeholder with no content so page creation will
// still work in this case.
return '' === $post_content ? '' : $post_content;
}//end et_fb_load_raw_post_content()
/**
* Remove custom style from our metabox when GB is showing it.
*
* @param string $post_type Post type.
*
* @access public.
* @return void
*/
public function add_meta_boxes( $post_type ) {
if ( is_gutenberg_page() ) {
// Change our metabox id so that no custom style is applied.
remove_meta_box( 'et_settings_meta_box', $post_type, 'side' );
add_meta_box(
'et_settings_meta_box_gutenberg',
esc_html__( 'Divi Page Settings', 'Divi' ),
'et_single_settings_meta_box',
$post_type,
'side',
'high'
);
}
}//end add_meta_boxes()
/**
* Hook into REST API page call.
*
* @access public.
* @return void
*/
public function rest_insert_page() {
add_filter( 'update_post_metadata', array( $this, 'update_post_metadata' ), 10, 4 );
}//end rest_insert_page()
/**
* Custom auth function for meta updates via REST API.
*
* @param boolean $allowed True if allowed to view the meta field by default, false if else.
* @param string $meta_key The meta key.
* @param int $id Post ID.
*
* @access public.
* @return bool
*/
public function meta_auth( $allowed, $meta_key, $id ) {
return current_user_can( 'edit_post', $id );
}//end meta_auth()
/**
* Hook methods to WordPress
* Latest plugin version: 1.5
* @return void
*/
public function init_hooks() {
if ( is_admin() ) {
add_action( 'enqueue_block_editor_assets', array( $this, 'enqueue_block_editor_assets' ), 4 );
add_action( 'admin_print_scripts-edit.php', array( $this, 'add_new_button' ), 10 );
add_action( 'admin_init', array( $this, 'add_edit_link_filters' ) );
// Only need to add this filter is the nonce is present in the url request
// nonce value will be checked in the filter itself.
if ( isset( $_GET['et_fb_new_vb_nonce'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.NoNonceVerification
add_action( 'new_to_auto-draft', array( $this, 'auto_draft' ), 1 );
}
add_filter( 'display_post_states', array( $this, 'display_post_states' ), 10, 2 );
}
add_filter( 'et_fb_load_raw_post_content', array( $this, 'et_fb_load_raw_post_content' ) );
// This is one of the most idiot things I had to do ever and its due to
// a 10 month old-yet not fixed WP bug: https://core.trac.wordpress.org/ticket/42069
// TLDR: when updating a post with meta via WP REST API, `update_metadata` should only
// be called for metas whose value changed.
// However, the equality check is fooled by values including characters that are
// slashed or converted to entities, like " or <.
// `update_metadata` is then called and returns `false` (because value didn't change) which results
// in REST API page update to abort with a 500 error code....
// To fix the issue, we hook into REST API page update and force `update_metadata` to return `true`
// when value didn't change (only applied to our own meta keys)
add_action( 'rest_insert_page', array( $this, 'rest_insert_page' ) );
// Need to deal with our metabox styling when inside GB
add_action( 'add_meta_boxes', array( $this, 'add_meta_boxes' ), 10, 1 );
// To register the post metas is needed because we want to change their value within our custom GB blocks
// Editing a post meta via REST API is allowed by default unless its key is protected (starts with `_`)
// which is the case here so we also need to create a custom auth function.
$auth = array( $this, 'meta_auth' );
register_meta( 'post', '_et_pb_use_builder', array(
'auth_callback' => $auth,
'show_in_rest' => true,
'single' => true,
'type' => 'string',
) );
register_meta( 'post', '_et_pb_old_content', array(
'auth_callback' => $auth,
'show_in_rest' => true,
'single' => true,
'type' => 'string',
) );
// Looks like this isn't needed for now
//add_filter( 'gutenberg_can_edit_post_type', array( $this, 'gutenberg_can_edit_post_type' ), 10, 2 );
}
}
new ET_Builder_Plugin_Compat_Gutenberg;