';
}
function ba_get_svg_clock_icon()
{
return '';
}
function ba_get_img_masking_shapes($shape)
{
$masking_shapes = array(
'none' => '',
'shape_1' => '',
'shape_2' => '',
'shape_3' => '',
);
return $masking_shapes[$shape];
}
function ba_get_post_types()
{
$post_types = get_post_types(
array(
'public' => true,
),
'objects'
);
$options = array();
foreach ($post_types as $post_type) {
$options[$post_type->name] = $post_type->label;
}
// Deprecated 'Media' post type.
$key = array_search('Media', $options, true);
if ('attachment' === $key) {
unset($options[$key]);
}
return apply_filters('uael_loop_post_types', $options);
}
function ba_get_taxonomies()
{
$taxonomies = get_taxonomies(array('show_in_nav_menus' => true), 'objects');
$options = array('' => '');
foreach ($taxonomies as $taxonomy) {
$options[$taxonomy->name] = $taxonomy->label;
}
return $options;
}
function ba_get_date_link($post_id = null)
{
if (empty($post_id)) {
$post_id = get_the_ID();
}
$year = get_the_date('Y', $post_id);
$month = get_the_time('m', $post_id);
$day = get_the_time('d', $post_id);
$url = get_day_link($year, $month, $day);
return $url;
}
function ba_get_excerpt($post_id = null, $length = null)
{
if (empty($length)) {
$length = 35;
}
return wpautop(strip_shortcodes(truncate_post($length, false, '', true)));
}
function ba_prev_arrow_icon()
{
return '';
}
function ba_next_arrow_icon()
{
return '';
}
if (!function_exists('dt_if_not_migrated')) {
function dt_if_not_migrated()
{
$not_migrated = get_option('ba_version');
if ($not_migrated) {
return true;
}
return false;
}
}
function dt_backend_helpers($helpers)
{
$helpers['ifMigrated'] = dt_if_not_migrated() ? 'false' : 'true';
return $helpers;
}
add_filter('et_fb_backend_helpers', 'dt_backend_helpers');
/**
* Track which icon-font asset handles this request needs.
*
* @param string|null $add Handle to mark as needed (et_icons_fa|et_icons_all).
*
* @return string[] All handles marked needed so far.
*/
if (!function_exists('dtq_needed_icon_assets')) {
function dtq_needed_icon_assets($add = null)
{
static $needed = array();
if (null !== $add) {
$needed[$add] = true;
}
return array_keys($needed);
}
}
if (!function_exists('dtq_global_assets_list')) {
function dtq_global_assets_list($global_list)
{
$assets_prefix = et_get_dynamic_assets_path();
$map = array(
'et_icons_fa' => "{$assets_prefix}/css/icons_fa_all.css",
'et_icons_all' => "{$assets_prefix}/css/icons_all.css",
);
$assets_list = array();
foreach (dtq_needed_icon_assets() as $handle) {
if (isset($map[$handle])) {
$assets_list[$handle] = array('css' => $map[$handle]);
}
}
return array_merge($global_list, $assets_list);
}
}
/**
* Ensure the correct icon font is loaded for a rendered icon.
*
* FontAwesome icons need the FA font; every other (Divi) icon needs the full
* Divi icon font (icons_all) — otherwise only the small base set renders and
* extended glyphs (e.g. warning) fall back to a literal letter.
*
* Pass the full "unicode||type||weight" string: et_pb_maybe_fa_font_icon()
* detects FontAwesome by the "||" separator, so a bare unicode is always read
* as a Divi icon and the FA font is never requested.
*
* The two filters below are DIVI 4 ONLY. Divi 4's Dynamic Assets still calls
* them, so they must stay. Divi 5 never fires them and has no third-party
* equivalent — see dtq_print_full_icon_font(), which is what actually delivers
* the font there.
*
* @param string $icon_data Icon value (unicode, optionally "||type||weight").
*/
if (!function_exists('dtq_inject_fa_icons')) {
function dtq_inject_fa_icons($icon_data)
{
$is_fa = function_exists('et_pb_maybe_fa_font_icon') && et_pb_maybe_fa_font_icon($icon_data);
dtq_needed_icon_assets($is_fa ? 'et_icons_fa' : 'et_icons_all');
add_filter('et_global_assets_list', 'dtq_global_assets_list');
add_filter('et_late_global_assets_list', 'dtq_global_assets_list');
}
}
/**
* Locate Divi on disk and on the web, whichever way it is installed.
*
* Divi 5 ships two ways: as the Divi (or Extra) theme, and as the Divi Builder
* plugin sitting under any third-party theme. get_template_directory_uri() is
* only correct for the first. Under the Builder plugin it returns the ACTIVE
* THEME, so a Divi-relative asset URL built from it 404s.
*
* That is worse than it sounds for @font-face: our rule prints at wp_footer 99,
* after Divi's own, and for a given family the last matching rule wins. A rule
* pointing at a 404 therefore *overrides* Divi's working font and breaks icons
* that would otherwise have rendered. Hence the file_exists() checks in
* dtq_icon_font_face() — we would rather emit nothing than emit a broken face.
*
* Mirrors Divi's own resolver, DynamicAssetsUtils::get_dynamic_assets_path().
*
* @return array{dir:string,uri:string} Divi root as a filesystem path and a URL.
*/
if (!function_exists('dtq_divi_root')) {
function dtq_divi_root()
{
if (
function_exists('et_is_builder_plugin_active') && et_is_builder_plugin_active()
&& defined('ET_BUILDER_PLUGIN_DIR') && defined('ET_BUILDER_PLUGIN_URI')
) {
return array(
'dir' => untrailingslashit(ET_BUILDER_PLUGIN_DIR),
'uri' => untrailingslashit(ET_BUILDER_PLUGIN_URI),
);
}
return array(
'dir' => untrailingslashit(get_template_directory()),
'uri' => untrailingslashit(get_template_directory_uri()),
);
}
}
/**
* Build one @font-face rule for a Divi-bundled icon font.
*
* Probes woff2 then woff and emits only the formats that actually exist, so the
* same call works for FontAwesome (ships woff2 + woff) and for ETmodules (ships
* woff, no woff2). Returns an empty string when no file is found, which is what
* keeps a wrong Divi root from producing a face that shadows a working one.
*
* @param string $family Font family name to declare.
* @param array $root Divi root from dtq_divi_root().
* @param string $rel Path below the Divi root, without extension.
* @param int $weight font-weight for this face.
*
* @return string One @font-face rule, or '' if the font files are missing.
*/
if (!function_exists('dtq_icon_font_face')) {
function dtq_icon_font_face($family, $root, $rel, $weight)
{
$sources = array();
foreach (array('woff2', 'woff') as $format) {
if (file_exists($root['dir'] . $rel . '.' . $format)) {
$sources[] = sprintf(
'url("%1$s") format("%2$s")',
esc_url($root['uri'] . $rel . '.' . $format),
$format
);
}
}
if (empty($sources)) {
return '';
}
return sprintf(
'@font-face{font-family:"%1$s";font-style:normal;font-weight:%2$d;font-display:swap;src:%3$s;}',
$family,
(int) $weight,
implode(',', $sources)
);
}
}
/**
* Ensure the icon fonts our modules just rendered are actually available.
*
* Two separate problems, one cure.
*
* ETmodules: Divi's "Dynamic Icons" feature only ships the subset of glyphs it
* detects in page content, and its detector does not see icons stored in our D5
* module attributes. Extended Divi icons (warning, star, heart, …) then have no
* glyph and fall back to a literal letter.
*
* FontAwesome: worse. dtq_inject_fa_icons() asks for the FA stylesheet through
* et_global_assets_list / et_late_global_assets_list, and under Divi 5 NEITHER
* FILTER EVER FIRES — verified by instrumenting both, plus their Divi 5
* replacements (divi_frontend_assets_dynamic_assets_[late_]global_assets_list),
* on a real front-end render. Divi 5 gates FA on $feature_state->use_fa_icons,
* set from DynamicAssetsUtils::get_font_icon_modules(), a hard-coded list of
* divi/* module names with no filter on it. A third-party module can never
* enter that list, so Divi will never load FA on our behalf and every FA icon
* renders as an empty box. There is no hook to fix this upstream; declare the
* faces ourselves.
*
* @param string[] $handles Handles to declare (et_icons_all|et_icons_fa).
*
* @return string The @font-face rules, or '' when none could be built.
*/
if (!function_exists('dtq_icon_font_css')) {
function dtq_icon_font_css($handles)
{
$root = dtq_divi_root();
$css = '';
if (in_array('et_icons_all', (array) $handles, true)) {
$css .= dtq_icon_font_face('ETmodules', $root, '/core/admin/fonts/modules/all/modules', 400);
}
if (in_array('et_icons_fa', (array) $handles, true)) {
// The three faces Divi's own icons_fa_all.css declares. Regular and
// Brands share weight 400 but cover disjoint codepoints, so both are
// needed and neither shadows the other.
$fa_faces = array(
array('fa-regular-400', 400),
array('fa-solid-900', 900),
array('fa-brands-400', 400),
);
foreach ($fa_faces as $face) {
$css .= dtq_icon_font_face('FontAwesome', $root, '/core/admin/fonts/fontawesome/' . $face[0], $face[1]);
}
}
return $css;
}
}
/**
* Print the icon fonts this request's modules actually rendered.
*
* Runs at wp_footer because dtq_needed_icon_assets() is only populated while
* modules render, which is long after wp_head. Emits nothing on a page with no
* icons, so the cost on the rest of the site is zero.
*/
if (!function_exists('dtq_print_full_icon_font')) {
function dtq_print_full_icon_font()
{
$css = dtq_icon_font_css(dtq_needed_icon_assets());
if ('' === $css) {
return;
}
// Element id kept from when this only handled ETmodules; changing it
// would break any site targeting it from custom CSS.
printf('', $css);
}
}
add_action('wp_footer', 'dtq_print_full_icon_font', 99);
/**
* Normalize an icon unicode value for output.
*
* Divi 4 stored icons either as a unicode entity ("àXX;", optionally with
* "||type||weight") or as the legacy index format "%%NN%%". When a layout using
* the legacy format is migrated to Divi 5, that "%%NN%%" string can survive into
* the D5 icon object's `unicode` field and would otherwise render as raw glyphs.
* Resolve it the same way Divi 4 did, via et_pb_process_font_icon().
*
* The result is escaped with esc_html() before it is returned: the stored value
* is a module attribute and therefore author-controlled, so printing it raw into
* the icon would let crafted markup reach the DOM. esc_html() passes
* `$double_encode = false`, so an existing "àXX;" entity survives untouched
* and the browser still renders the glyph — the call is idempotent for entities.
*
* @param string $unicode Raw unicode value from the icon attribute.
*
* @return string Escaped unicode entity, safe to print inside the icon .
*/
if (!function_exists('dtq_resolve_icon_unicode')) {
function dtq_resolve_icon_unicode($unicode)
{
$unicode = (string) $unicode;
if (false !== strpos($unicode, '%%') && function_exists('et_pb_process_font_icon')) {
// et_pb_process_font_icon() returns the entity with the ampersand already
// escaped ("àXX;"); decode once so the raw entity ("àXX;") is
// what lands inside the icon and the browser renders the glyph.
$unicode = html_entity_decode(et_pb_process_font_icon($unicode));
}
return esc_html($unicode);
}
}
/**
* mbstring-safe string helpers.
*
* mbstring is not guaranteed to be present — it is a non-default PHP extension
* and some shared hosts ship without it. Calling mb_* unguarded is a fatal on
* those hosts, which took the whole page down whenever a module truncated an
* excerpt. These wrappers fall back to the single-byte equivalents; the fallback
* can split a multi-byte character mid-sequence, which is cosmetically imperfect
* but far better than a white screen.
*/
if (!function_exists('dtq_strlen')) {
function dtq_strlen($string)
{
$string = (string) $string;
return function_exists('mb_strlen') ? mb_strlen($string) : strlen($string);
}
}
if (!function_exists('dtq_substr')) {
function dtq_substr($string, $start, $length = null)
{
$string = (string) $string;
if (function_exists('mb_substr')) {
return null === $length ? mb_substr($string, $start) : mb_substr($string, $start, $length);
}
return null === $length ? substr($string, $start) : substr($string, $start, $length);
}
}
if (!function_exists('dtq_strimwidth')) {
function dtq_strimwidth($string, $start, $width, $trim_marker = '')
{
$string = (string) $string;
if (function_exists('mb_strimwidth')) {
return mb_strimwidth($string, $start, $width, $trim_marker);
}
return dtq_strimwidth_fallback($string, $start, $width, $trim_marker);
}
}
/**
* Single-byte implementation of dtq_strimwidth().
*
* Split out from the wrapper so it stays reachable — and therefore testable —
* on hosts that DO have mbstring, where the wrapper always delegates. Matches
* mb_strimwidth(), including its quirk of returning the trim marker itself when
* $width is not larger than the marker.
*/
if (!function_exists('dtq_strimwidth_fallback')) {
function dtq_strimwidth_fallback($string, $start, $width, $trim_marker = '')
{
$slice = substr((string) $string, $start);
if (strlen($slice) <= $width) {
return $slice;
}
return substr($slice, 0, max(0, $width - strlen($trim_marker))) . $trim_marker;
}
}
/**
* Resolve a Divi `$variable(...)$` token (global colour / variable) to CSS.
*
* Divi 5 stores a global colour as an encoded `$variable({...})$` string. Style
* output that bypasses Divi's own resolver emits that token literally, so the
* colour renders as raw text instead of a colour. Run author-supplied values
* through this before sanitizing them.
*
* Returns the value unchanged when it holds no dynamic variable, or when Divi's
* resolver is unavailable.
*
* @param mixed $value Raw attribute value.
*
* @return mixed
*/
if (!function_exists('dtq_resolve_css_value')) {
function dtq_resolve_css_value($value)
{
if (is_string($value)
&& false !== strpos($value, '$variable(')
&& class_exists('\ET\Builder\Packages\StyleLibrary\Utils\Utils')
) {
return \ET\Builder\Packages\StyleLibrary\Utils\Utils::resolve_dynamic_variables_recursive($value);
}
return $value;
}
}
/**
* Sanitize a colour value destined for interpolation into a CSS declaration.
*
* Module colour attributes are author-controlled. Interpolating them into a
* stylesheet unchecked lets a value such as `#fff}