: str_replace(): Passing null to parameter #2 ($replace) of type array|string is deprecated in
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly
// get_plugins() is only available on dashboard; Manually require it needed.
if ( ! function_exists( 'get_plugins' ) ) {
require_once ABSPATH . 'wp-admin/includes/plugin.php';
class ET_Builder_Error_Report {
* @var ET_Core_Data_Utils
* @var ET_Builder_Error_Report
private static $_instance;
* ET_Builder_Error_Report constructor.
public function __construct() {
add_action( 'wp_ajax_et_fb_error_report', array( 'ET_Builder_Error_Report', 'endpoint' ) );
* json_decode data and stripslashes if needed.
public static function json_decode_maybe_stripslashes( $data ) {
$decoded = json_decode( $data, true );
if ( null === $decoded ) {
$decoded = json_decode( stripslashes( $data ), true );
* Get the class instance.
* @return ET_Builder_Error_Report
public static function instance() {
if ( ! self::$_instance ) {
self::$_instance = new self;
self::$_ = ET_Core_Data_Utils::instance();
* Get information sent for error reporting
static public function get_debug_info() {
// If the site uses divi builder plugin, provide the theme information
if ( et_is_builder_plugin_active() ) {
// If the site uses child theme, provide the child theme information
if ( is_child_theme() ) {
* Get current product name
protected function get_product() {
if ( et_is_builder_plugin_active() ) {
if ( function_exists( 'et_divi_fonts_url' ) ) {
if ( function_exists( 'et_extra_fonts_url' ) ) {
* @param string $info_name debug info item name
* @param object $post alias for $_POST
* @return string|array|object
protected function get_debug_value( $info_name, $post ) {
$current_user = wp_get_current_user();
$value = esc_html( implode( ', ', $current_user->roles ) );
case 'error_message_stack':
// this will be saved into a text report, no need to convert entities.
$value = self::$_->array_get( $post, $info_name, '' );
$value = et_fb_process_to_shortcode( self::$_->array_get( $post, $info_name, array() ) );
$value = wp_json_encode( self::$_->array_get( $post, $info_name, array() ) );
foreach ( et_fb_app_preferences() as $name => $preference ) {
$value[ $name ] = $preference['value'];
$value = wp_json_encode( $value );
$value = $this->get_product();
$value = et_is_builder_plugin_active() ?
self::$_->array_get( get_plugin_data( WP_PLUGIN_DIR . '/' . 'divi-builder/divi-builder.php' ), 'Version', '' ) :
$value = esc_html( $value );
$value = ET_BUILDER_PRODUCT_VERSION;
$value = esc_html( get_bloginfo( 'version' ) );
case 'installed_plugins':
$all_plugins = get_plugins();
$value = wp_json_encode( array_keys( $all_plugins ), true );
$all_plugins = get_plugins();
$active_plugins_saved = get_option( 'active_plugins' );
$active_plugins_keys = is_array( $active_plugins_saved ) ? $active_plugins_saved : array();
$active_plugins = array_intersect_key( $all_plugins, array_flip( $active_plugins_keys ) );
$value = wp_json_encode( $active_plugins, true );
$value = wp_json_encode( get_mu_plugins(), true );
$value = esc_html( wp_get_theme()->get( 'Name' ) );
case 'child_theme_version':
$value = esc_html__( wp_get_theme()->get( 'Version' ) );
$value = is_child_theme() ? 'yes' : 'no';
* Get error report content
protected function get_report_content( $data ) {
$debug_info = self::get_debug_info();
$report_content = array();
foreach ( $debug_info as $items_title => $debug_items ) {
$item_key = 'group_title-' . $items_title;
$items_title = ucwords( $items_title );
$report_content[ $item_key ] = $items_title;
foreach ( $debug_items as $debug_item ) {
$item_value = et_core_esc_previously( $this->get_debug_value( $debug_item, $data, 'array' ) );
$report_content[ $debug_item ] = $item_value;
* Get attachment data as string to be passed into endpoint
protected function get_exported_layout_content( $data, $field ) {
// Set faux $_POST value that is required by portability
$_POST['post'] = $_POST['post_id'];
$_POST['content'] = self::$_instance->get_debug_value( $field , $data );
// Remove page value if it is equal to `false`, avoiding paginated images not accidentally triggered
if ( isset( $_POST['page'] ) && false === $_POST['page'] ) {
$portability = et_core_portability_load( 'et_builder' );
$result = $portability->export( true );
// Delete temp files or else the same content will be used for all exports.
$portability->delete_temp_files( 'et_core_export' );
* Endpoint for sending error report request
static public function endpoint() {
// Check for valid permission. Only administrator role can send error report
if ( ! et_core_security_check_passed( 'manage_options', 'et_fb_send_error_report' ) ) {
wp_send_json_error( array(
'message' => esc_html__( 'You do not have valid permission to send error report', 'et_builder' ),
$post_id = self::$_->array_get( $_POST, 'post_id', false );
wp_send_json_error( array(
'message' => esc_html__( 'No valid post id found', 'et_builder' ),
$data = self::$_->array_get( $_POST, 'data', false );
wp_send_json_error( array(
'message' => esc_html__( 'No valid report data found', 'et_builder' ),
// Check for Elegant Themes username & API Key
$updates_options = get_site_option( 'et_automatic_updates_options', array() );
$et_username = self::$_->array_get( $updates_options, 'username', '' );
$et_api_key = self::$_->array_get( $updates_options, 'api_key', '' );
if ( '' === $et_username || '' === $et_api_key ) {
wp_send_json_error( array(
'message' => esc_html__( 'No Elegant Themes username or API key found', 'et_builder' ),
// Check for account status
$et_account_status = get_site_option( 'et_account_status', 'not_active' );
if ( 'active' !== $et_account_status ) {
wp_send_json_error( array(
'message' => esc_html__( 'Your Elegant Themes account is inactive', 'et_builder' ),
$data = self::json_decode_maybe_stripslashes( $data );
$et_endpoint = apply_filters( 'et_builder_report_endpoint', 'https://www.elegantthemes.com/api/reportV2.php' );
// Crafting reports and send to end endpoint.
$request_settings = array(
'username' => $et_username,
'api_key' => $et_api_key,
'error_report' => self::$_instance->get_report_content( $data ),
'site_url' => site_url(),
'latest' => self::$_instance->get_exported_layout_content( $data, 'latest_content' ),
'loaded' => self::$_instance->get_exported_layout_content( $data, 'loaded_content' ),
$request = wp_remote_post( $et_endpoint, $request_settings );
$request_response_code = wp_remote_retrieve_response_code( $request );
$request_body = wp_remote_retrieve_body( $request );
if ( 200 === $request_response_code ) {
wp_send_json_error( json_decode( $request_body ) );
ET_Builder_Error_Report::instance();