: str_replace(): Passing null to parameter #2 ($replace) of type array|string is deprecated in
'title' => esc_attr__( 'An Overview Of All Divi Modules', 'et-core' ),
'url' => 'https://www.elegantthemes.com/documentation/divi/modules/',
'title' => esc_attr__( 'Getting Started With Layout Packs', 'et-core' ),
'url' => 'https://www.elegantthemes.com/documentation/divi/premade-layouts/',
'title' => esc_attr__( 'Customizing Your Header And Navigation', 'et-core' ),
'url' => 'https://www.elegantthemes.com/documentation/extra/theme-customizer/',
'title' => esc_attr__( 'Getting Started With The Divi Builder', 'et-core' ),
'url' => 'https://www.elegantthemes.com/documentation/divi/visual-builder/',
'title' => esc_attr__( 'How To Update The Divi Theme', 'et-core' ),
'url' => 'https://www.elegantthemes.com/documentation/divi/update-divi/',
'title' => esc_attr__( 'An Overview Of All Divi Modules', 'et-core' ),
'url' => 'https://www.elegantthemes.com/documentation/divi/modules/',
'title' => esc_attr__( 'Using The Divi Library', 'et-core' ),
'url' => 'https://www.elegantthemes.com/documentation/divi/divi-library/',
'title' => esc_attr__( 'Setting Up The Divi Theme Options', 'et-core' ),
'url' => 'https://www.elegantthemes.com/documentation/divi/theme-options/',
'title' => esc_attr__( 'Getting Started With Layout Packs', 'et-core' ),
'url' => 'https://www.elegantthemes.com/documentation/divi/premade-layouts/',
'title' => esc_attr__( 'Customizing Your Header And Navigation', 'et-core' ),
'url' => 'https://www.elegantthemes.com/documentation/divi/customizer-header/',
'title' => esc_attr__( 'Divi For Developers', 'et-core' ),
'url' => 'https://www.elegantthemes.com/documentation/developers/',
case 'divi_builder_plugin':
'title' => esc_attr__( 'Getting Started With The Divi Builder', 'et-core' ),
'url' => 'https://www.elegantthemes.com/documentation/divi/visual-builder/',
'title' => esc_attr__( 'How To Update The Divi Builder', 'et-core' ),
'url' => 'https://www.elegantthemes.com/documentation/divi-builder/update-divi-builder/',
'title' => esc_attr__( 'An Overview Of All Divi Modules', 'et-core' ),
'url' => 'https://www.elegantthemes.com/documentation/divi/modules/',
'title' => esc_attr__( 'Using The Divi Library', 'et-core' ),
'url' => 'https://www.elegantthemes.com/documentation/divi/divi-library/',
'title' => esc_attr__( 'Selling Products With Divi And WooCommerce', 'et-core' ),
'url' => 'https://www.elegantthemes.com/documentation/divi/ecommerce-divi/',
'title' => esc_attr__( 'Getting Started With Layout Packs', 'et-core' ),
'url' => 'https://www.elegantthemes.com/documentation/divi/premade-layouts/',
'title' => esc_attr__( 'Importing And Exporting Divi Layouts', 'et-core' ),
'url' => 'https://www.elegantthemes.com/documentation/divi/library-import/',
'title' => esc_attr__( 'Divi For Developers', 'et-core' ),
'url' => 'https://www.elegantthemes.com/documentation/developers/',
'title' => esc_attr__( 'A Basic Overview Of The Bloom Plugin', 'et-core' ),
'url' => 'https://www.elegantthemes.com/documentation/bloom/overview/',
'title' => esc_attr__( 'How To Update Your Bloom Plugin', 'et-core' ),
'url' => 'https://www.elegantthemes.com/documentation/bloom/update/',
'title' => esc_attr__( 'Adding Email Accounts In Bloom', 'et-core' ),
'url' => 'https://www.elegantthemes.com/documentation/bloom/accounts/',
'title' => esc_attr__( 'Customizing Your Opt-in Designs', 'et-core' ),
'url' => 'https://www.elegantthemes.com/documentation/bloom/design/',
'title' => esc_attr__( 'The Different Bloom Opt-in Types', 'et-core' ),
'url' => 'https://www.elegantthemes.com/documentation/bloom/optin-types/',
'title' => esc_attr__( 'Using The Bloom Display Settings', 'et-core' ),
'url' => 'https://www.elegantthemes.com/documentation/bloom/display/',
'title' => esc_attr__( 'How To Use Triggers In Bloom', 'et-core' ),
'url' => 'https://www.elegantthemes.com/documentation/bloom/triggers/',
'title' => esc_attr__( 'Adding Custom Fields To Bloom Opt-in Forms', 'et-core' ),
'url' => 'https://www.elegantthemes.com/documentation/bloom/optin/adding-custom-fields-to-bloom-optin-forms/',
'title' => esc_attr__( 'A Complete Overview Of The Monarch Plugin', 'et-core' ),
'url' => 'https://www.elegantthemes.com/documentation/monarch/overview-monarch/',
'title' => esc_attr__( 'How To Update Your Monarch WordPress Plugin', 'et-core' ),
'url' => 'https://www.elegantthemes.com/documentation/monarch/update-monarch/',
'title' => esc_attr__( 'Adding and Managing Social Networks', 'et-core' ),
'url' => 'https://www.elegantthemes.com/documentation/monarch/networks/',
'title' => esc_attr__( 'Configuring Social Network APIs', 'et-core' ),
'url' => 'https://www.elegantthemes.com/documentation/monarch/api/',
'title' => esc_attr__( 'Customizing The Monarch Design', 'et-core' ),
'url' => 'https://www.elegantthemes.com/documentation/monarch/design-monarch/',
'title' => esc_attr__( 'Viewing Your Social Stats', 'et-core' ),
'url' => 'https://www.elegantthemes.com/documentation/monarch/stats/',
'title' => esc_attr__( 'Using The Floating Sidebar', 'et-core' ),
'url' => 'https://www.elegantthemes.com/documentation/monarch/sidebar/',
'title' => esc_attr__( 'Using Popup & Flyin Triggers', 'et-core' ),
'url' => 'https://www.elegantthemes.com/documentation/monarch/triggers-monarch/',
// If we just want the array (not a formatted HTML block), return that now
if ( false === $formatted ) {
foreach ( $articles as $key => $article ) {
$articles_list_html .= sprintf(
'<li class="et-support-center-article"><a href="%1$s" target="_blank">%2$s</a></li>',
esc_url( $article['url'] ),
et_core_intentionally_unescaped( $article['title'], 'fixed_string' )
'<div class="et_docs_articles"><ul class="et_documentation_articles_list">%1$s</ul></div>',
* Look for Elegant Themes Support Account
* @return WP_User|false WP_User object on success, false on failure.
public function get_et_support_user() {
return get_user_by( 'slug', $this->support_user_account_name );
* Look for saved Elegant Themes Username & API Key
* @return array|false license credentials on success, false on failure.
public function get_et_license() {
/** @var array License credentials [username|api_key] */
if ( ! $et_license = get_site_option( 'et_automatic_updates_options' ) ) {
$et_license = get_option( 'et_automatic_updates_options', array() );
if ( ! et_()->array_get( $et_license, 'username' ) ) {
if ( ! et_()->array_get( $et_license, 'api_key' ) ) {
* Try to load the WP debug log. If found, return the last [$lines_to_return] lines of the file and the filesize.
* @param int $lines_to_return Number of lines to read and return from the end of the wp_debug.log file.
protected function get_wp_debug_log( $lines_to_return = 10 ) {
// Early exit: internal PHP function `file_get_contents()` appears to be on lockdown
if ( ! function_exists( 'file_get_contents' ) ) {
$log['error'] = esc_attr__( 'Divi Support Center :: WordPress debug log cannot be read.', 'et-core' );
if ( defined( 'ET_DEBUG' ) ) {
et_error( $log['error'] );
// Early exit: WP_DEBUG_LOG isn't defined in wp-config.php (or it's defined, but it's empty)
if ( ! defined( 'WP_DEBUG_LOG' ) || ! WP_DEBUG_LOG ) {
$log['error'] = esc_attr__( 'Divi Support Center :: WordPress debug.log is not configured.', 'et-core' );
if ( defined( 'ET_DEBUG' ) ) {
et_error( $log['error'] );
* WordPress 5.1 introduces the option to define a custom path for the WP_DEBUG_LOG file.
if ( in_array( strtolower( (string) WP_DEBUG_LOG ), array( 'true', '1' ), true ) ) {
$wp_debug_log_path = realpath( WP_CONTENT_DIR . '/debug.log' );
} else if ( is_string( WP_DEBUG_LOG ) ) {
$wp_debug_log_path = realpath( WP_DEBUG_LOG );
// Early exit: `debug.log` doesn't exist or otherwise can't be read
if ( ! isset( $wp_debug_log_path ) || ! file_exists( $wp_debug_log_path ) || ! is_readable( $wp_debug_log_path ) ) {
$log['error'] = esc_attr__( 'Divi Support Center :: WordPress debug log cannot be found.', 'et-core' );
if ( defined( 'ET_DEBUG' ) ) {
et_error( $log['error'] );
* At this point, we know:
* (1) `$wp_debug_log_path` is set,
* (2) it points to a valid location, and
* (3) what it points to is readable.
* Before we continue, we'll ensure `$wp_debug_log_path` does not point to a directory.
// Early exit: debug log definition points to a directory, not a file.
if ( is_dir( $wp_debug_log_path ) ) {
$log['error'] = esc_attr__(
'Divi Support Center :: WordPress debug log setting points to a directory, but should point to a file.',
if ( defined( 'ET_DEBUG' ) ) {
et_error( $log['error'] );
// Load the debug.log file
$file = new SplFileObject( $wp_debug_log_path );
// Get the filesize of debug.log
$log['size'] = $this->get_size_in_shorthand( 0 + $file->getSize() );
// If $lines_to_return is a positive integer, fetch the last [$lines_to_return] lines of the log file
$lines_to_return = (int) $lines_to_return;
if ( $lines_to_return > 0 ) {
$file->seek( PHP_INT_MAX );
$total_lines = $file->key();
// If the file is smaller than the number of lines requested, return the entire file.
$reader = new LimitIterator( $file, max( 0, $total_lines - $lines_to_return ) );
foreach ( $reader as $line ) {
$log['entries'] .= $line;
// Unload the SplFileObject
* When a predefined system setting is passed to this function, it will return the observed value.
* @param bool $formatted Whether to return a formatted report or just the data array
* @param string $format Return the report as either a `div` or `plain` text (if $formatted = true)
protected function system_diagnostics_generate_report( $formatted = true, $format = 'plain' ) {
/** @var array Collection of system settings to run diagnostic checks on. */
$system_diagnostics_settings = array(
'name' => esc_attr__( 'Writable wp-content Directory', 'et-core' ),
'environment' => 'server',
'type' => 'truthy_falsy',
'pass_minus_one' => null,
'actual' => wp_is_writable( WP_CONTENT_DIR ),
'help_text' => et_core_intentionally_unescaped( __( 'We recommend that the wp-content directory on your server be writable by WordPress in order to ensure the full functionality of Divi Builder themes and plugins.', 'et-core' ), 'html' ),
'learn_more' => 'https://wordpress.org/support/article/changing-file-permissions/',
'name' => esc_attr__( 'PHP Version', 'et-core' ),
'environment' => 'server',
'pass_minus_one' => false,
'recommended' => '7.2 or higher',
'actual' => (float) phpversion(),
'help_text' => et_core_intentionally_unescaped( __( 'We recommend using the latest stable version of PHP. This will not only ensure compatibility with Divi, but it will also greatly speed up your website leading to less memory and CPU related issues.', 'et-core' ), 'html' ),
'learn_more' => 'http://php.net/releases/',
'name' => esc_attr__( 'memory_limit', 'et-core' ),
'environment' => 'server',
'pass_minus_one' => true,
'actual' => ini_get( 'memory_limit' ),
'help_text' => et_get_safe_localization( sprintf( __( 'By default, memory limits set by your host or by WordPress may be too low. This will lead to applications crashing as PHP reaches the artificial limit. You can adjust your memory limit within your <a href="%1$s" target="_blank">php.ini file</a>, or by contacting your host for assistance. You may also need to define a memory limited in <a href="%2$s" target=_blank">wp-config.php</a>.', 'et-core' ), 'http://php.net/manual/en/ini.core.php#ini.memory-limit', 'https://codex.wordpress.org/Editing_wp-config.php' ) ),
'learn_more' => 'http://php.net/manual/en/ini.core.php#ini.memory-limit',
'name' => esc_attr__( 'post_max_size', 'et-core' ),
'environment' => 'server',
'pass_minus_one' => false,
'actual' => ini_get( 'post_max_size' ),
'help_text' => et_get_safe_localization( sprintf( __( 'Post Max Size limits how large a page or file can be on your website. If your page is larger than the limit set in PHP, it will fail to load. Post sizes can become quite large when using the Divi Builder, so it is important to increase this limit. It also affects file size upload/download, which can prevent large layouts from being imported into the builder. You can adjust your max post size within your <a href="%1$s" target="_blank">php.ini file</a>, or by contacting your host for assistance.', 'et_core' ), 'http://php.net/manual/en/ini.core.php#ini.post-max-size' ) ),
'learn_more' => 'http://php.net/manual/en/ini.core.php#ini.post-max-size',
'name' => esc_attr__( 'max_execution_time', 'et-core' ),
'environment' => 'server',
'pass_minus_one' => false,
'actual' => ini_get( 'max_execution_time' ),
'help_text' => et_get_safe_localization( sprintf( __( 'Max Execution Time affects how long a page is allowed to load before it times out. If the limit is too low, you may not be able to import large layouts and files into the builder. You can adjust your max execution time within your <a href="%1$s">php.ini file</a>, or by contacting your host for assistance.', 'et-core' ), 'http://php.net/manual/en/info.configuration.php#ini.max-execution-time' ) ),
'learn_more' => 'http://php.net/manual/en/info.configuration.php#ini.max-execution-time',
'name' => esc_attr__( 'upload_max_filesize', 'et-core' ),
'environment' => 'server',
'pass_minus_one' => false,
'actual' => ini_get( 'upload_max_filesize' ),
'help_text' => et_get_safe_localization( sprintf( __( 'Upload Max File Size determines that maximum file size that you are allowed to upload to your server. If the limit is too low, you may not be able to import large collections of layouts into the Divi Library. You can adjust your max file size within your <a href="%1$s" target="_blank">php.ini file</a>, or by contacting your host for assistance.', 'et-core' ), 'http://php.net/manual/en/ini.core.php#ini.upload-max-filesize' ) ),
'learn_more' => 'http://php.net/manual/en/ini.core.php#ini.upload-max-filesize',
'name' => esc_attr__( 'max_input_time', 'et-core' ),
'environment' => 'server',
'pass_minus_one' => true,
'actual' => ini_get( 'max_input_time' ),
'help_text' => et_get_safe_localization( sprintf( __( 'This sets the maximum time in seconds a script is allowed to parse input data. If the limit is too low, the Divi Builder may time out before it is allowed to load. You can adjust your max input time within your <a href="%1$s" target="_blank">php.ini file</a>, or by contacting your host for assistance.', 'et-core' ), 'http://php.net/manual/en/info.configuration.php#ini.max-input-time' ) ),
'learn_more' => 'http://php.net/manual/en/info.configuration.php#ini.max-input-time',
'name' => esc_attr__( 'max_input_vars', 'et-core' ),
'environment' => 'server',
'pass_minus_one' => false,
'actual' => ini_get( 'max_input_vars' ),
'help_text' => et_get_safe_localization( sprintf( __( 'This setting affects how many input variables may be accepted. If the limit is too low, it may prevent the Divi Builder from loading. You can adjust your max input variables within your <a href="%1$s" target="_blank">php.ini file</a>, or by contacting your host for assistance.', 'et-core' ), 'http://php.net/manual/en/info.configuration.php#ini.max-input-vars' ) ),
'learn_more' => 'http://php.net/manual/en/info.configuration.php#ini.max-input-vars',
'name' => esc_attr__( 'display_errors', 'et-core' ),
'environment' => 'server',
'type' => 'truthy_falsy',
'pass_minus_one' => null,
'actual' => ! ini_get( 'display_errors' ) ? '0' : ini_get( 'display_errors' ),
'help_text' => et_get_safe_localization( sprintf( __( 'This setting determines whether or not errors should be printed as part of the page output. This is a feature to support your site\'s development and should never be used on production sites. You can edit this setting within your <a href="%1$s" target="_blank">php.ini file</a>, or by contacting your host for assistance.', 'et-core' ), 'http://php.net/manual/en/errorfunc.configuration.php#ini.display-errors' ) ),
'learn_more' => 'http://php.net/manual/en/errorfunc.configuration.php#ini.display-errors',
/** @var string Formatted report. */
// pass/fail Should be one of pass|minimal|fail|unknown. Defaults to 'unknown'.
foreach ( $system_diagnostics_settings as $i => $scan ) {
* 'pass_fail': four-step process to set its value:
* - begin with `unknown` state;
* - if recommended value exists, change to `fail`;
* - if minimum value exists, compare against it & change to `minimal` if it passes;
* - compare against recommended value & change to `pass` if it passes.
$system_diagnostics_settings[ $i ]['pass_fail'] = 'unknown';
if ( ! is_null( $scan['recommended'] ) ) {
$system_diagnostics_settings[ $i ]['pass_fail'] = 'fail';
if ( ! is_null( $scan['minimum'] ) && $this->value_is_at_least( $scan['minimum'], $scan['actual'], $scan['type'] ) ) {
$system_diagnostics_settings[ $i ]['pass_fail'] = 'minimal';
if ( empty( $scan['pass_exact'] ) && ! is_null( $scan['recommended'] ) && $this->value_is_at_least( $scan['recommended'], $scan['actual'], $scan['type'] ) ) {
$system_diagnostics_settings[ $i ]['pass_fail'] = 'pass';
if ( $scan['pass_minus_one'] && -1 === (int) $scan['actual'] ) {
$system_diagnostics_settings[ $i ]['pass_fail'] = 'pass';
if ( $scan['pass_zero'] && 0 === (int) $scan['actual'] ) {
$system_diagnostics_settings[ $i ]['pass_fail'] = 'pass';
if ( ! empty( $scan['pass_exact'] ) && $scan['recommended'] === $scan['actual'] ) {
$system_diagnostics_settings[ $i ]['pass_fail'] = 'pass';
* Build messaging for minimum required values
if ( ! is_null( $scan['minimum'] ) && 'fail' === $system_diagnostics_settings[ $i ]['pass_fail'] ) {
$message_minimum = sprintf(
esc_html__( 'This fails to meet our minimum required value of %1$s. ', 'et-core' ),
esc_html( is_bool( $scan['minimum'] ) ? $this->boolean_label[ $scan['minimum'] ] : $scan['minimum'] )
if ( ! is_null( $scan['minimum'] ) && 'minimal' === $system_diagnostics_settings[ $i ]['pass_fail'] ) {