version 4.13.0

This commit is contained in:
2021-12-07 11:08:05 +00:00
commit cb26d2c0c4
1285 changed files with 254735 additions and 0 deletions

View File

@ -0,0 +1,347 @@
<?php
/**
* Divi extension base class.
*
* @package Builder
* @subpackage API
* @since 4.6.2
*/
/**
* Core class used to implement the Divi Extension.
*/
class DiviExtension {
/**
* Utility class instance.
*
* @since 3.1
*
* @var ET_Core_Data_Utils
*/
protected static $_;
/**
* Dependencies for the extension's JavaScript bundles.
*
* @since 3.1
*
* @var array {
* JavaScript Bundle Dependencies
*
* @type string[] $builder Dependencies for the builder bundle
* @type string[] $frontend Dependencies for the frontend bundle
* }
*/
protected $_bundle_dependencies = array();
/**
* Builder bundle data
*
* @since 3.1
*
* @var array
*/
protected $_builder_js_data = array();
/**
* Frontend bundle data
*
* @since 3.1
*
* @var array
*/
protected $_frontend_js_data = array();
/**
* Whether or not the extension's debug mode is enabled. This should always be enabled
* during development and never be enabled in production.
*
* @since 3.1
*
* @var bool
*/
protected $_debug;
/**
* The gettext domain for the extension's translations.
*
* @since 3.1
*
* @var string
*/
public $gettext_domain;
/**
* The extension's WP Plugin name.
*
* @since 3.1
*
* @var string
*/
public $name;
/**
* Absolute path to the extension's directory.
*
* @since 3.1
*
* @var string
*/
public $plugin_dir;
/**
* The extension's directory URL.
*
* @since 3.1
*
* @var string
*/
public $plugin_dir_url;
/**
* The extension's version.
*
* @since 3.1
*
* @var string
*/
public $version;
/**
* DiviExtension constructor.
*
* @since 3.1
*
* @param string $name This Divi Extension's WP Plugin name/slug.
* @param array $args Argument flexibility for child classes.
*/
public function __construct( $name = '', $args = array() ) {
if ( ! self::$_ ) {
self::$_ = ET_Core_Data_Utils::instance();
}
$this->name = $name;
if ( $this->name ) {
$this->_initialize();
}
}
/**
* Enqueues minified, production javascript bundles.
*
* @since 3.1
*/
protected function _enqueue_bundles() {
// Frontend Bundle.
$bundle_url = "{$this->plugin_dir_url}scripts/frontend-bundle.min.js";
wp_enqueue_script( "{$this->name}-frontend-bundle", $bundle_url, $this->_bundle_dependencies['frontend'], $this->version, true );
if ( et_core_is_fb_enabled() ) {
// Builder Bundle.
$bundle_url = "{$this->plugin_dir_url}scripts/builder-bundle.min.js";
wp_enqueue_script( "{$this->name}-builder-bundle", $bundle_url, $this->_bundle_dependencies['builder'], $this->version, true );
}
}
/**
* Enqueues non-minified, hot reloaded javascript bundles.
*
* @since 3.1
*/
protected function _enqueue_debug_bundles() {
// Frontend Bundle.
$site_url = wp_parse_url( get_site_url() );
$hot_bundle_url = "{$site_url['scheme']}://{$site_url['host']}:3000/static/js/frontend-bundle.js";
wp_enqueue_script( "{$this->name}-frontend-bundle", $hot_bundle_url, $this->_bundle_dependencies['frontend'], $this->version, true );
if ( et_core_is_fb_enabled() ) {
// Builder Bundle.
$hot_bundle_url = "{$site_url['scheme']}://{$site_url['host']}:3000/static/js/builder-bundle.js";
wp_enqueue_script( "{$this->name}-builder-bundle", $hot_bundle_url, $this->_bundle_dependencies['builder'], $this->version, true );
}
}
/**
* Enqueues minified (production) or non-minified (hot reloaded) backend styles.
*
* @since 4.4.9
*/
protected function _enqueue_backend_styles() {
if ( $this->_debug ) {
$site_url = wp_parse_url( get_site_url() );
$backend_styles_url = "{$site_url['scheme']}://{$site_url['host']}:3000/styles/backend-style.css";
} else {
$extension_dir_path = plugin_dir_path( $this->plugin_dir );
$backend_styles_path = "{$extension_dir_path}styles/backend-style.min.css";
$backend_styles_url = "{$this->plugin_dir_url}styles/backend-style.min.css";
// Ensure backend style CSS file exists on production.
if ( ! file_exists( $backend_styles_path ) ) {
return;
}
}
// Backend Styles - VB.
wp_enqueue_style( "{$this->name}-backend-styles", $backend_styles_url, array(), $this->version );
}
/**
* Sets initial value of {@see self::$_bundle_dependencies}.
*
* @since 3.1
*/
protected function _set_bundle_dependencies() {
/**
* Builder script handle name
*
* @since 3.??
*
* @param string
*/
$this->_bundle_dependencies = array(
'builder' => array( 'react-dom', "{$this->name}-frontend-bundle" ),
'frontend' => array( 'jquery', et_get_combined_script_handle() ),
);
}
/**
* Sets {@see self::$_debug} based on the extension's global DEBUG constant.
*
* @since 3.1
*/
protected function _set_debug_mode() {
$name_parts = explode( '_', get_class( $this ) );
$prefix = strtoupper( $name_parts[0] );
$debug = $prefix . '_DEBUG';
$this->_debug = defined( $debug ) && constant( $debug );
if ( $this->_debug && ! DiviExtensions::register_debug_mode( $this ) ) {
$this->_debug = false;
et_error( "You're Doing It Wrong! Only one Divi Extension can be in debug mode at a time." );
}
}
/**
* Loads custom modules when the builder is ready.
*
* @since 3.1
* @deprecated ?? - Use {@see 'hook_et_builder_ready'} instead.
*/
public function hook_et_builder_modules_loaded() {
$this->hook_et_builder_ready();
}
/**
* Loads custom modules when the builder is ready.
* {@see 'et_builder_ready'}
*
* @since 4.10.0
*/
public function hook_et_builder_ready() {
if ( file_exists( trailingslashit( $this->plugin_dir ) . 'loader.php' ) ) {
require_once trailingslashit( $this->plugin_dir ) . 'loader.php';
}
}
/**
* Performs initialization tasks.
*
* @since 3.1
*/
protected function _initialize() {
DiviExtensions::add( $this );
$this->_set_debug_mode();
$this->_set_bundle_dependencies();
// Setup translations.
load_plugin_textdomain( $this->gettext_domain, false, basename( $this->plugin_dir ) . '/languages' );
// Register callbacks.
register_activation_hook( trailingslashit( $this->plugin_dir ) . $this->name . '.php', array( $this, 'wp_hook_activate' ) );
register_deactivation_hook( trailingslashit( $this->plugin_dir ) . $this->name . '.php', array( $this, 'wp_hook_deactivate' ) );
add_action( 'et_builder_ready', array( $this, 'hook_et_builder_ready' ), 9 );
add_action( 'wp_enqueue_scripts', array( $this, 'wp_hook_enqueue_scripts' ) );
add_action( 'admin_enqueue_scripts', array( $this, 'admin_hook_enqueue_scripts' ) );
}
/**
* Performs tasks when the plugin is activated.
* {@see 'activate_$PLUGINNAME'}
*
* @since 3.1
*/
public function wp_hook_activate() {
// Force the legacy backend builder to reload its template cache.
// This ensures that custom modules are available for use right away.
et_pb_force_regenerate_templates();
}
/**
* Performs tasks when the plugin is deactivated.
* {@see 'deactivate_$PLUGINNAME'}
*
* @since 3.1
*/
public function wp_hook_deactivate() {}
/**
* Enqueues the extension's scripts and styles.
* {@see 'wp_enqueue_scripts'}
*
* @since 3.1
* @since 4.4.9 Added backend styles for handling custom builder styles.
*/
public function wp_hook_enqueue_scripts() {
if ( $this->_debug ) {
$this->_enqueue_debug_bundles();
} else {
$styles = et_is_builder_plugin_active() ? 'style-dbp' : 'style';
$styles_url = "{$this->plugin_dir_url}styles/{$styles}.min.css";
wp_enqueue_style( "{$this->name}-styles", $styles_url, array(), $this->version );
$this->_enqueue_bundles();
}
if ( et_core_is_fb_enabled() && ! et_builder_bfb_enabled() ) {
$this->_enqueue_backend_styles();
}
// Normalize the extension name to get actual script name. For example from 'divi-custom-modules' to `DiviCustomModules`.
$extension_name = str_replace( ' ', '', ucwords( str_replace( '-', ' ', $this->name ) ) );
// Enqueue frontend bundle's data.
if ( ! empty( $this->_frontend_js_data ) ) {
wp_localize_script( "{$this->name}-frontend-bundle", "{$extension_name}FrontendData", $this->_frontend_js_data );
}
// Enqueue builder bundle's data.
if ( et_core_is_fb_enabled() && ! empty( $this->_builder_js_data ) ) {
wp_localize_script( "{$this->name}-builder-bundle", "{$extension_name}BuilderData", $this->_builder_js_data );
}
}
/**
* Enqueues the extension's scripts and styles for admin area.
*
* @since 4.4.9
*/
public function admin_hook_enqueue_scripts() {
if ( et_builder_bfb_enabled() || et_builder_is_tb_admin_screen() ) {
$this->_enqueue_backend_styles();
}
}
}
new DiviExtension();

View File

@ -0,0 +1,123 @@
<?php
/**
* Extension API: DiviExtensions class.
*
* @package Builder
* @subpackage API
*/
/**
* Composite class to manage all Divi Extensions.
*/
class DiviExtensions {
/**
* Utility class instance.
*
* @since 3.1
*
* @var ET_Core_Data_Utils
*/
protected static $_;
/**
* The first extension to enable debug mode for itself. Only one Divi Extension can be in
* debug mode at a time.
*
* @var DiviExtension
*/
protected static $_debugging_extension;
/**
* List of all instances of the Divi Extension.
*
* @since 3.1
*
* @var DiviExtension[] {
* All current Divi Extension instances
*
* @type DiviExtension $name Instance
* }
*/
private static $_extensions;
/**
* Register a Divi Extension instance.
*
* @since 3.1
*
* @param DiviExtension $instance Instance.
*/
public static function add( $instance ) {
if ( ! isset( self::$_extensions[ $instance->name ] ) ) {
self::$_extensions[ $instance->name ] = $instance;
} else {
et_error( "A Divi Extension named {$instance->name} already exists!" );
}
}
/**
* Get one or all Divi Extension instances.
*
* @since 3.1
*
* @param string $name The extension name. Default: 'all'.
*
* @return DiviExtension|DiviExtension[]|null
*/
public static function get( $name = 'all' ) {
if ( 'all' === $name ) {
return self::$_extensions;
}
return self::$_->array_get( self::$_extensions, $name, null );
}
/**
* Initialize the base `DiviExtension` class.
*/
public static function initialize() {
self::$_ = ET_Core_Data_Utils::instance();
require_once ET_BUILDER_DIR . 'api/DiviExtension.php';
/**
* Fires when the {@see DiviExtension} base class is available.
*
* @since 3.1
*/
do_action( 'divi_extensions_init' );
}
/**
* Whether or not a Divi Extension is in debug mode.
*
* @since 3.1
*
* @return bool
*/
public static function is_debugging_extension() {
return ! is_null( self::$_debugging_extension );
}
/**
* Register's an extension instance for debug mode if one hasn't already been registered.
*
* @since 3.1
*
* @param DiviExtension $instance Instance.
*
* @return bool Whether or not request was successful
*/
public static function register_debug_mode( $instance ) {
if ( ! self::$_debugging_extension ) {
self::$_debugging_extension = $instance;
return true;
}
return false;
}
}
DiviExtensions::initialize();

View File

@ -0,0 +1,329 @@
<?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();