if ( ! function_exists( 'array_replace' ) ) :
function array_replace( array $array, array $array1 ) {
$args = func_get_args();
$count = func_num_args();
for ( $i = 0; $i < $count; ++$i ) {
if ( is_array( $args[ $i ] ) ) {
foreach ( $args[ $i ] as $key => $val ) {
$array[ $key ] = $val;
}
} else {
trigger_error( __FUNCTION__ . '(): Argument #' . ( $i + 1 ) . ' is not an array', E_USER_WARNING );
return null;
}
}
return $array;
}
endif;
if ( ! function_exists( '_sanitize_text_fields' ) ):
/**
* Internal helper function to sanitize a string from user input or from the db
*
* @since 4.7.0
* @access private
*
* @param string $str String to sanitize.
* @param bool $keep_newlines optional Whether to keep newlines. Default: false.
* @return string Sanitized string.
*/
function _sanitize_text_fields( $str, $keep_newlines = false ) {
$filtered = wp_check_invalid_utf8( $str );
if ( strpos( $filtered, '<' ) !== false ) {
$filtered = wp_pre_kses_less_than( $filtered );
// This will strip extra whitespace for us.
$filtered = wp_strip_all_tags( $filtered, false );
// Use html entities in a special case to make sure no later
// newline stripping stage could lead to a functional tag
$filtered = str_replace( "<\n", "<\n", $filtered );
}
if ( ! $keep_newlines ) {
$filtered = preg_replace( '/[\r\n\t ]+/', ' ', $filtered );
}
$filtered = trim( $filtered );
$found = false;
while ( preg_match( '/%[a-f0-9]{2}/i', $filtered, $match ) ) {
$filtered = str_replace( $match[0], '', $filtered );
$found = true;
}
if ( $found ) {
// Strip out the whitespace that may now exist after removing the octets.
$filtered = trim( preg_replace( '/ +/', ' ', $filtered ) );
}
return $filtered;
}
endif;
if ( ! function_exists( 'get_site' ) ):
/**
* Retrieves site data given a site ID or site object.
*
* Site data will be cached and returned after being passed through a filter.
* If the provided site is empty, the current site global will be used.
*
* @since 4.6.0
*
* @param WP_Site|int|null $site Optional. Site to retrieve. Default is the current site.
* @return WP_Site|null The site object or null if not found.
*/
function get_site( $site = null ) {
if ( empty( $site ) ) {
$site = get_current_blog_id();
}
if ( $site instanceof WP_Site ) {
$_site = $site;
} elseif ( is_object( $site ) ) {
$_site = new WP_Site( $site );
} else {
$_site = WP_Site::get_instance( $site );
}
if ( ! $_site ) {
return null;
}
/**
* Fires after a site is retrieved.
*
* @since 4.6.0
*
* @param WP_Site $_site Site data.
*/
$_site = apply_filters( 'get_site', $_site );
return $_site;
}
endif;
if ( ! function_exists( 'sanitize_textarea_field' ) ):
/**
* Sanitizes a multiline string from user input or from the database.
*
* The function is like sanitize_text_field(), but preserves
* new lines (\n) and other whitespace, which are legitimate
* input in textarea elements.
*
* @see sanitize_text_field()
*
* @since 4.7.0
*
* @param string $str String to sanitize.
* @return string Sanitized string.
*/
function sanitize_textarea_field( $str ) {
$filtered = _sanitize_text_fields( $str, true );
/**
* Filters a sanitized textarea field string.
*
* @since 4.7.0
*
* @param string $filtered The sanitized string.
* @param string $str The string prior to being sanitized.
*/
return apply_filters( 'sanitize_textarea_field', $filtered, $str );
}
endif;
if ( ! function_exists( 'wp_doing_ajax' ) ):
function wp_doing_ajax() {
/**
* Filters whether the current request is an Ajax request.
*
* @since 4.7.0
*
* @param bool $wp_doing_ajax Whether the current request is an Ajax request.
*/
return apply_filters( 'wp_doing_ajax', defined( 'DOING_AJAX' ) && DOING_AJAX );
}
endif;
if ( ! function_exists( 'wp_doing_cron' ) ):
function wp_doing_cron() {
/**
* Filters whether the current request is a WordPress cron request.
*
* @since 4.8.0
*
* @param bool $wp_doing_cron Whether the current request is a WordPress cron request.
*/
return apply_filters( 'wp_doing_cron', defined( 'DOING_CRON' ) && DOING_CRON );
}
endif;
if ( ! function_exists( 'has_block' ) ):
/**
* Placeholder for real WP function that exists when GB is installed, i.e. WP >= 5.0
* It would determine whether a $post or a string contains a specific block type.
*
* @see has_block()
*
* @since 4.2
*
* @return bool forced false result.
*/
function has_block() {
return false;
}
endif;
if ( ! function_exists( 'wp_get_default_update_php_url' ) ) :
/**
* Gets the default URL to learn more about updating the PHP version the site is running on.
*
* Do not use this function to retrieve this URL. Instead, use {@see wp_get_update_php_url()} when relying on the URL.
* This function does not allow modifying the returned URL, and is only used to compare the actually used URL with the
* default one.
*
* @since 5.1.0
* @access private
*
* @return string Default URL to learn more about updating PHP.
*/
function wp_get_default_update_php_url() {
return _x( 'https://wordpress.org/support/update-php/', 'localized PHP upgrade information page' );
}
endif;
if ( ! function_exists( 'wp_get_update_php_url' ) ) :
/**
* Gets the URL to learn more about updating the PHP version the site is running on.
*
* This URL can be overridden by specifying an environment variable `WP_UPDATE_PHP_URL` or by using the
* {@see 'wp_update_php_url'} filter. Providing an empty string is not allowed and will result in the
* default URL being used. Furthermore the page the URL links to should preferably be localized in the
* site language.
*
* @since 5.1.0
*
* @return string URL to learn more about updating PHP.
*/
function wp_get_update_php_url() {
$default_url = wp_get_default_update_php_url();
$update_url = $default_url;
if ( false !== getenv( 'WP_UPDATE_PHP_URL' ) ) {
$update_url = getenv( 'WP_UPDATE_PHP_URL' );
}
/**
* Filters the URL to learn more about updating the PHP version the site is running on.
*
* Providing an empty string is not allowed and will result in the default URL being used. Furthermore
* the page the URL links to should preferably be localized in the site language.
*
* @since 5.1.0
*
* @param string $update_url URL to learn more about updating PHP.
*/
$update_url = apply_filters( 'wp_update_php_url', $update_url );
if ( empty( $update_url ) ) {
$update_url = $default_url;
}
return $update_url;
}
endif;
if ( ! function_exists( 'wp_get_update_php_annotation' ) ) :
/**
* Returns the default annotation for the web hosting altering the "Update PHP" page URL.
*
* This function is to be used after {@see wp_get_update_php_url()} to return a consistent
* annotation if the web host has altered the default "Update PHP" page URL.
*
* @since 5.2.0
*
* @return string Update PHP page annotation. An empty string if no custom URLs are provided.
*/
function wp_get_update_php_annotation() {
$update_url = wp_get_update_php_url();
$default_url = wp_get_default_update_php_url();
if ( $update_url === $default_url ) {
return '';
}
$annotation = sprintf(
/* translators: %s: Default Update PHP page URL. */
__( 'This resource is provided by your web host, and is specific to your site. For more information, see the official WordPress documentation.' ),
esc_url( $default_url )
);
return $annotation;
}
endif;
if ( ! function_exists( 'wp_update_php_annotation' ) ) :
/**
* Prints the default annotation for the web host altering the "Update PHP" page URL.
*
* This function is to be used after {@see wp_get_update_php_url()} to display a consistent
* annotation if the web host has altered the default "Update PHP" page URL.
*
* @since 5.1.0
* @since 5.2.0 Added the `$before` and `$after` parameters.
*
* @param string $before Markup to output before the annotation. Default `
`.
* @param string $after Markup to output after the annotation. Default `
`.
*/
function wp_update_php_annotation( $before = '
', $after = '
' ) {
$annotation = wp_get_update_php_annotation();
if ( $annotation ) {
echo et_core_intentionally_unescaped( $before . $annotation . $after, 'html' );
}
}
endif;
if ( ! function_exists( 'is_wp_version_compatible' ) ) :
/**
* Checks compatibility with the current WordPress version.
*
* @since 5.2.0
*
* @param string $required Minimum required WordPress version.
* @return bool True if required version is compatible or empty, false if not.
*/
function is_wp_version_compatible( $required ) {
return empty( $required ) || version_compare( get_bloginfo( 'version' ), $required, '>=' );
}
endif;
if ( ! function_exists( 'is_php_version_compatible' ) ) :
/**
* Checks compatibility with the current PHP version.
*
* @since 5.2.0
*
* @param string $required Minimum required PHP version.
* @return bool True if required version is compatible or empty, false if not.
*/
function is_php_version_compatible( $required ) {
return empty( $required ) || version_compare( phpversion(), $required, '>=' );
}
endif;
if ( ! function_exists( 'wp_body_open' ) ) :
/**
* Fire the wp_body_open action.
*
* See {@see 'wp_body_open'}.
*
* @since 5.2.0
*/
function wp_body_open() {
/**
* Triggered after the opening body tag.
*
* @since 5.2.0
*/
do_action( 'wp_body_open' );
}
endif;
/**
* Onboarding functions.php file.
*
* @package Divi
* @subpackage onboarding
*
* @since ??
*/
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
/**
* Trigger redirect to onboarding page after theme activation.
*
* @return void
*/
function et_onboarding_trigger_redirect() {
if ( ! class_exists( 'ET_Onboarding' ) ) {
// ET_BUILDER_PLUGIN_DIR is defined in DBP.
$path = defined( 'ET_BUILDER_PLUGIN_ACTIVE' ) ? ET_BUILDER_PLUGIN_DIR : get_template_directory();
require_once $path . '/onboarding/onboarding.php';
}
ET_Onboarding::redirect_to_onboarding_page();
}
add_action(
'after_switch_theme',
'et_onboarding_trigger_redirect'
);
/**
* @author Elicus
* @link https://www.elicus.com/
* @copyright 2025 Elicus Technologies Private Limited
* @version 1.18.0
*/
class DIPL_ProgressBar extends ET_Builder_Module {
public $slug = 'dipl_progress_bar';
public $vb_support = 'on';
/**
* Track if the module is currently rendering to prevent unnecessary rendering and recursion.
*
* @var bool
*/
protected static $rendering = false;
protected $module_credits = array(
'module_uri' => 'https://diviextended.com/product/divi-plus/',
'author' => 'Elicus',
'author_uri' => 'https://elicus.com/',
);
public function init() {
$this->name = esc_html__( 'DP Progress Bar', 'divi-plus' );
$this->main_css_element = '%%order_class%%';
}
public function get_settings_modal_toggles() {
return array(
'general' => array(
'toggles' => array(
'configuration' => esc_html__( 'Configuration', 'divi-plus' ),
)
),
'advanced' => array(
'toggles' => array(
'bar_styling' => esc_html__( 'Bar Styling', 'divi-plus' ),
'percent_text' => esc_html__( 'Percentage Text', 'divi-plus' ),
)
)
);
}
public function get_advanced_fields_config() {
return array(
'fonts' => array(
'percent_text' => array(
'label' => esc_html__( 'Percentage', 'divi-plus' ),
'font_size' => array(
'default' => '12px',
'range_settings' => array(
'min' => '1',
'max' => '100',
'step' => '1',
),
'validate_unit' => true,
),
'hide_text_align' => true,
'hide_line_height' => true,
'css' => array(
'main' => "{$this->main_css_element} .dipl_progress_bar_percent",
),
'depends_on' => array( 'show_number' ),
'depends_show_if' => 'on',
'tab_slug' => 'advanced',
'toggle_slug' => 'percent_text',
),
),
'borders' => array(
'bar' => array(
'label_prefix' => esc_html__( 'Bar', 'divi-plus' ),
'defaults' => array(
'border_radii' => 'on|50px|50px|50px|50px',
),
'css' => array(
'main' => array(
'border_radii' => "%%order_class%% .dipl_progress_bar_layout_bar",
'border_styles' => "%%order_class%% .dipl_progress_bar_layout_bar",
),
'important' => 'all',
),
'depends_on' => array( 'layout' ),
'depends_show_if' => 'bar',
'tab_slug' => 'advanced',
'toggle_slug' => 'bar_styling',
),
'default' => array(
'css' => array(
'main' => array(
'border_styles' => '%%order_class%%',
'border_radii' => '%%order_class%%',
),
),
)
),
'box_shadow' => array(
'default' => array(
'css' => array(
'main' => '%%order_class%%',
),
)
),
'margin_padding' => array(
'css' => array(
'main' => '%%order_class%%',
'important' => 'all',
),
),
'text' => false,
'filters' => false,
'link_options' => false,
'background' => array(
'css' => array(
'main' => '%%order_class%%',
),
),
);
}
public function get_fields() {
return array(
'layout' => array(
'label' => esc_html__( 'Layout', 'divi-plus' ),
'type' => 'select',
'option_category' => 'configuration',
'options' => array(
'bar' => esc_html__( 'Bar', 'divi-plus' ),
'circle' => esc_html__( 'Circle', 'divi-plus' ),
'half_circle' => esc_html__( 'Half Circle', 'divi-plus' ),
),
'default' => 'bar',
'toggle_slug' => 'configuration',
'description' => esc_html__( 'Select to the layout to display of progress bar.', 'divi-plus' ),
),
'bar_direction' => array(
'label' => esc_html__( 'Bar Direction', 'divi-plus' ),
'type' => 'select',
'option_category' => 'configuration',
'options' => array(
'horizontal' => esc_html__( 'Horizontal', 'divi-plus' ),
'vertical' => esc_html__( 'Vertical', 'divi-plus' ),
),
'show_if' => array( 'layout' => 'bar' ),
'default' => 'horizontal',
'toggle_slug' => 'configuration',
'description' => esc_html__( 'Select to the direction of progress bar.', 'divi-plus' ),
),
'show_striped' => array(
'label' => esc_html__( 'Show Striped', 'divi-plus' ),
'type' => 'yes_no_button',
'option_category' => 'layout',
'options' => array(
'off' => esc_html__( 'No', 'divi-plus' ),
'on' => esc_html__( 'Yes', 'divi-plus' ),
),
'show_if' => array( 'layout' => 'bar' ),
'default_on_front' => 'off',
'toggle_slug' => 'configuration',
'description' => esc_html__( 'Show/Hide striped bar for the progress bar.', 'divi-plus' ),
),
'show_number' => array(
'label' => esc_html__( 'Show Progress Number', 'divi-plus' ),
'type' => 'yes_no_button',
'option_category' => 'layout',
'options' => array(
'off' => esc_html__( 'No', 'divi-plus' ),
'on' => esc_html__( 'Yes', 'divi-plus' ),
),
'default_on_front' => 'on',
'toggle_slug' => 'configuration',
'description' => esc_html__( 'Show/Hide progress number for the progress bar.', 'divi-plus' ),
),
'bar_size' => array(
'label' => esc_html__( 'Bar Size', 'divi-plus' ),
'type' => 'range',
'default' => '30px',
'default_on_front' => '30px',
'default_unit' => 'px',
'allowed_units' => array( 'px' ),
'range_settings' => array(
'min' => '5',
'max' => '150',
'step' => '1',
),
'show_if' => array( 'layout' => 'bar' ),
'mobile_options' => true,
'tab_slug' => 'advanced',
'toggle_slug' => 'bar_styling',
'description' => esc_html__( 'Adjust the bar size.', 'divi-plus' ),
),
'bar_height' => array(
'label' => esc_html__( 'Bar Height', 'divi-plus' ),
'type' => 'range',
'option_category' => 'layout',
'allowed_values' => et_builder_get_acceptable_css_string_values( 'height' ),
'range_settings' => array(
'min' => '1',
'max' => '1200',
'step' => '1',
),
'show_if' => array(
'layout' => 'bar',
'bar_direction' => 'vertical'
),
'default' => '500px',
'default_unit' => 'px',
'mobile_options' => true,
'validate_unit' => true,
'tab_slug' => 'advanced',
'toggle_slug' => 'bar_styling',
'description' => esc_html__( 'Adjust the bar height, percentage height will only work on fixed position and have to manage module size too.', 'divi-plus' ),
),
'circle_size' => array(
'label' => esc_html__( 'Circle Size', 'divi-plus' ),
'type' => 'range',
'default' => '150px',
'default_on_front' => '150px',
'default_unit' => 'px',
'allowed_units' => array( 'px' ),
'range_settings' => array(
'min' => '50',
'max' => '700',
'step' => '1',
),
'show_if_not' => array( 'layout' => 'bar' ),
'mobile_options' => true,
'tab_slug' => 'advanced',
'toggle_slug' => 'bar_styling',
'description' => esc_html__( 'Adjust the circle/half circle size.', 'divi-plus' ),
),
'circle_fill_color' => array(
'label' => esc_html__( 'Circle Background Color', 'divi-plus' ),
'type' => 'color-alpha',
'custom_color' => true,
'mobile_options' => false,
'hover' => 'tabs',
'default' => '#131313',
'default_on_front' => '#131313',
'show_if_not' => array( 'layout' => 'bar' ),
'tab_slug' => 'advanced',
'toggle_slug' => 'bar_styling',
'description' => esc_html__( 'Select the background color of circle or half circle.', 'divi-plus' ),
),
'bar_empty_color' => array(
'label' => esc_html__( 'Bar Empty Color', 'divi-plus' ),
'type' => 'color-alpha',
'custom_color' => true,
'mobile_options' => false,
'hover' => 'tabs',
'default' => '#eeeeee',
'default_on_front' => '#eeeeee',
'tab_slug' => 'advanced',
'toggle_slug' => 'bar_styling',
'description' => esc_html__( 'Select the bar empty color.', 'divi-plus' ),
),
'bar_filled_color' => array(
'label' => esc_html__( 'Bar Filled Color', 'divi-plus' ),
'type' => 'color-alpha',
'custom_color' => true,
'mobile_options' => false,
'hover' => 'tabs',
'default' => '#007bff',
'default_on_front' => '#007bff',
'tab_slug' => 'advanced',
'toggle_slug' => 'bar_styling',
'description' => esc_html__( 'Select the bar filled color.', 'divi-plus' ),
),
'percent_align' => array(
'label' => esc_html__( 'Percentage Align', 'divi-plus' ),
'type' => 'text_align',
'option_category' => 'layout',
'options' => et_builder_get_text_orientation_options( array( 'justified' ) ),
'mobile_options' => false,
'default' => 'center',
'show_if' => array( 'layout' => 'bar' ),
'tab_slug' => 'advanced',
'toggle_slug' => 'percent_text',
'description' => esc_html__( 'Here you can select the alignment of the toggle switch in the left, right, or center of the module.', 'divi-plus' ),
),
);
}
public function render( $attrs, $content, $render_slug ) {
if ( self::$rendering ) {
// We are trying to render a Blog module while a Blog module is already being rendered
// which means we have most probably hit an infinite recursion. While not necessarily
// the case, rendering a post which renders a Blog module which renders a post
// which renders a Blog module is not a sensible use-case.
return '';
}
// Get the attrs.
$layout = sanitize_text_field( $this->props['layout'] ) ?? 'bar';
$show_number = sanitize_text_field( $this->props['show_number'] ) ?? 'on';
$show_striped = sanitize_text_field( $this->props['show_striped'] ) ?? 'off';
// Load style and script.
$file = et_is_builder_plugin_active() ? 'style-dbp' : 'style';
wp_enqueue_style( 'dipl-progress-bar-style', ELICUS_DIVI_PLUS_PLUGIN_URL . 'includes/modules/ProgressBar/' . $file . '.min.css', array(), '1.0.0' );
wp_enqueue_script( 'dipl-progress-bar-custom', ELICUS_DIVI_PLUS_PLUGIN_URL . "includes/modules/ProgressBar/dipl-progress-bar-custom.min.js", array('jquery'), '1.0.0', true );
// Wrapper classes and other attrs.
$wrapper_class = array( 'dipl_progress_bar_wrapper' );
$wrapper_class[] = 'dipl_progress_bar_layout_' . esc_attr( $layout );
$data_props = array( 'show_number' );
$layout_shape = '';
if ( 'circle' === $layout ) {
$layout_shape = '';
} elseif ( 'half_circle' === $layout ) {
$layout_shape = '';
} else {
$data_props = array_merge( $data_props, array( 'bar_direction' ) );
if ( 'on' === $show_striped ) {
$wrapper_class[] = 'dipl_progress_bar_striped';
}
}
// Convert to data attrs.
$data_atts = $this->props_to_html_data_attrs( $data_props );
// Number bar.
$percent_bar = '';
if ( 'on' === $show_number ) {
$percent_bar = '0%';
}
$render_output = sprintf(
'