Ok, I was able to resolve the issue by overriding the set_default_values function in the shortcode class.
I added the function from enfold/config-templatebuilder/avia-template-builder/php/shortcode-template.class.php
/**
* helper function executed by aviaShortcodeTemplate::popup_editor that extracts the attributes from the shortcode and then merges the values into the options array
*
* @param array $elements
* @return array $elements
*/
public function set_default_values($elements)
{
$shortcode = !empty($_POST['params']['shortcode']) ? $_POST['params']['shortcode'] : '';
if($shortcode)
{
//will extract the shortcode into $_POST['extracted_shortcode']
$this->builder->text_to_interface($shortcode);
//the main shortcode (which is always the last array item) will be stored in $extracted_shortcode
$extracted_shortcode = end($_POST['extracted_shortcode']);
//if the $_POST['extracted_shortcode'] has more than one items we are dealing with nested shortcodes
$multi_content = count($_POST['extracted_shortcode']);
//proceed if the main shortcode has either arguments or content
if(!empty($extracted_shortcode['attr']) || !empty($extracted_shortcode['content']))
{
if(empty($extracted_shortcode['attr'])) $extracted_shortcode['attr'] = array();
if(isset($extracted_shortcode['content'])) $extracted_shortcode['attr']['content'] = $extracted_shortcode['content'];
//iterate over each array item and check if we already got a value
foreach($elements as &$element)
{
if(isset($element['id']) && isset($extracted_shortcode['attr'][$element['id']]))
{
//make sure that each element of the popup can access the other values of the shortcode. necessary for hidden elements
$element['shortcode_data'] = $extracted_shortcode['attr'];
//if the item has subelements the std value has to be an array
if(isset($element['subelements']))
{
$element['std'] = array();
for ($i = 0; $i < $multi_content - 1; $i++)
{
$element['std'][$i] = $_POST['extracted_shortcode'][$i]['attr'];
$element['std'][$i]['content'] = $_POST['extracted_shortcode'][$i]['content'];
}
}
else
{
$element['std'] = stripslashes($extracted_shortcode['attr'][$element['id']]);
}
}
else
{
if($element['type'] == "checkbox") $element['std'] = '';
}
}
}
}
return $elements;
}
I modified it to be as follows:
/**
* helper function executed by aviaShortcodeTemplate::popup_editor that extracts the attributes from the shortcode and then merges the values into the options array
*
* @param array $elements
* @return array $elements
*/
public function set_default_values($elements)
{
$shortcode = !empty($_POST['params']['shortcode']) ? $_POST['params']['shortcode'] : '';
if($shortcode)
{
//will extract the shortcode into $_POST['extracted_shortcode']
$this->builder->text_to_interface($shortcode);
//the main shortcode (which is always the last array item) will be stored in $extracted_shortcode
$extracted_shortcode = end($_POST['extracted_shortcode']);
//if the $_POST['extracted_shortcode'] has more than one items we are dealing with nested shortcodes
$multi_content = count($_POST['extracted_shortcode']);
//proceed if the main shortcode has either arguments or content
if(!empty($extracted_shortcode['attr']) || !empty($extracted_shortcode['content']))
{
if(empty($extracted_shortcode['attr'])) $extracted_shortcode['attr'] = array();
if(isset($extracted_shortcode['content'])) $extracted_shortcode['attr']['content'] = $extracted_shortcode['content'];
//iterate over each array item and check if we already got a value
foreach($elements as &$element)
{
if(isset($element['id']) && isset($extracted_shortcode['attr'][$element['id']]))
{
//make sure that each element of the popup can access the other values of the shortcode. necessary for hidden elements
$element['shortcode_data'] = $extracted_shortcode['attr'];
//if the item has subelements the std value has to be an array
if(isset($element['subelements']))
{
$element['std'] = array();
for ($i = 0; $i < $multi_content - 1; $i++)
{
$element['std'][$i] = $_POST['extracted_shortcode'][$i]['attr'];
$element['std'][$i]['content'] = $_POST['extracted_shortcode'][$i]['content'];
}
}
else
{
$element['std'] = html_entity_decode(stripslashes($extracted_shortcode['attr'][$element['id']]));
}
}
else
{
if($element['type'] == "checkbox") $element['std'] = '';
}
}
}
}
return $elements;
}
The difference is that I changed this:
$element['std'] = stripslashes($extracted_shortcode['attr'][$element['id']]);
to this:
$element['std'] = html_entity_decode(stripslashes($extracted_shortcode['attr'][$element['id']]));
and included it in my shortcode element, which is finished below:
<?php
/**
* 2 Column Module
*
* Builds 2 column modules with image on one side and content on the other.
*/
if ( ! defined( 'ABSPATH' ) ) { exit; } // Exit if accessed directly
if ( ! class_exists( 'avia_sc_two_column_module' ) )
{
class avia_sc_two_column_module extends aviaShortcodeTemplate
{
/**
* Create the config array for the shortcode button
*/
function shortcode_insert_button()
{
$this->config['version'] = '1.0';
$this->config['self_closing'] = 'yes';
$this->config['name'] = __( '2 Column Modules', 'avia_framework' );
$this->config['tab'] = __( 'Content Elements', 'avia_framework' );
$this->config['icon'] = AviaBuilder::$path['imagesURL'] . 'sc-blog.png';
$this->config['order'] = 40;
$this->config['target'] = 'avia-target-insert';
$this->config['shortcode'] = 'av_two_column_module';
$this->config['tooltip'] = __( 'Builds 2 Column Modules ', 'avia_framework' );
$this->config['preview'] = false;
$this->config['id_name'] = 'id';
$this->config['id_show'] = 'yes';
$this->config['alb_desc_id'] = 'alb_description';
}
function admin_assets()
{
$ver = AviaBuilder::VERSION;
}
function extra_assets()
{
wp_enqueue_style( 'two-column-module', get_stylesheet_directory_uri() . '/shortcodes/assets/twocolumnmodule.css', array( 'avia-layout' ), false );
}
/**
* helper function executed by aviaShortcodeTemplate::popup_editor that extracts the attributes from the shortcode and then merges the values into the options array
*
* @param array $elements
* @return array $elements
*/
public function set_default_values($elements)
{
$shortcode = !empty($_POST['params']['shortcode']) ? $_POST['params']['shortcode'] : '';
if($shortcode)
{
//will extract the shortcode into $_POST['extracted_shortcode']
$this->builder->text_to_interface($shortcode);
//the main shortcode (which is always the last array item) will be stored in $extracted_shortcode
$extracted_shortcode = end($_POST['extracted_shortcode']);
//if the $_POST['extracted_shortcode'] has more than one items we are dealing with nested shortcodes
$multi_content = count($_POST['extracted_shortcode']);
//proceed if the main shortcode has either arguments or content
if(!empty($extracted_shortcode['attr']) || !empty($extracted_shortcode['content']))
{
if(empty($extracted_shortcode['attr'])) $extracted_shortcode['attr'] = array();
if(isset($extracted_shortcode['content'])) $extracted_shortcode['attr']['content'] = $extracted_shortcode['content'];
//iterate over each array item and check if we already got a value
foreach($elements as &$element)
{
if(isset($element['id']) && isset($extracted_shortcode['attr'][$element['id']]))
{
//make sure that each element of the popup can access the other values of the shortcode. necessary for hidden elements
$element['shortcode_data'] = $extracted_shortcode['attr'];
//if the item has subelements the std value has to be an array
if(isset($element['subelements']))
{
$element['std'] = array();
for ($i = 0; $i < $multi_content - 1; $i++)
{
$element['std'][$i] = $_POST['extracted_shortcode'][$i]['attr'];
$element['std'][$i]['content'] = $_POST['extracted_shortcode'][$i]['content'];
}
}
else
{
$element['std'] = html_entity_decode(stripslashes($extracted_shortcode['attr'][$element['id']]));
}
}
else
{
if($element['type'] == "checkbox") $element['std'] = '';
}
}
}
}
return $elements;
}
/**
* Popup Elements
*
* If this function is defined in a child class the element automatically gets an edit button, that, when pressed
* opens a modal window that allows to edit the element properties
*
* @return void
*/
function popup_elements()
{
$this->elements = array(
array(
'type' => 'tab_container',
'nodescription' => true
),
array(
'type' => 'tab',
'name' => __( 'Content', 'avia_framework' ),
'nodescription' => true
),
array(
'type' => 'template',
'template_id' => 'toggle_container',
'templates_include' => array(
$this->popup_key( 'selected_project' )
),
'nodescription' => true
),
array(
'type' => 'tab_close',
'nodescription' => true
),
array(
'type' => 'tab',
'name' => __( 'Advanced', 'avia_framework' ),
'nodescription' => true
),
array(
'type' => 'toggle_container',
'nodescription' => true
),
array(
'type' => 'template',
'template_id' => 'screen_options_toggle'
),
array(
'type' => 'template',
'template_id' => 'developer_options_toggle',
'args' => array( 'sc' => $this )
),
array(
'type' => 'toggle_container_close',
'nodescription' => true
),
array(
'type' => 'tab_close',
'nodescription' => true
),
array(
'type' => 'tab_container_close',
'nodescription' => true
)
);
}
/**
* Create and register templates for easier maintainance
*
* @since 4.6.4
*/
protected function register_dynamic_templates()
{
/**
* Content Tab
* ===========
*/
$c = array(
array(
'name' => __( 'Module Content', 'avia_framework' ),
'desc' => __( 'What is the content for this module?', 'avia_framework' ),
'id' => 'module_content',
'type' => 'tiny_mce',
'std' => '',
),
array(
'name' => __( 'Module Image', 'avia_framework' ),
'desc' => __( 'What is image for this module? (Select Large if available, Full Size if Large is not available.)', 'avia_framework' ),
'id' => 'module_image',
'type' => 'image',
'title' => __( 'Insert Image', 'avia_framework' ),
'button' => __( 'Insert', 'avia_framework' ),
'std' => AviaBuilder::$path['imagesURL'] . 'placeholder.jpg'
),
array(
'name' => __( 'Image Side?', 'avia_framework' ),
'desc' => __( 'What side of the module will the image be on?', 'avia_framework' ),
'id' => 'image_side',
'type' => 'select',
'std' => 'left',
'subtype' => array(
__( 'Left', 'avia_framework' ) => 'left',
__( 'Right', 'avia_framework' ) => 'right'
)
)
);
$template = array(
array(
'type' => 'template',
'template_id' => 'toggle',
'title' => __( '2 Column Module', 'avia_framework' ),
'content' => $c
),
);
AviaPopupTemplates()->register_dynamic_template( $this->popup_key( 'selected_project' ), $template );
}
/**
* Editor Element - this function defines the visual appearance of an element on the AviaBuilder Canvas
* Most common usage is to define some markup in the $params['innerHtml'] which is then inserted into the drag and drop container
* Less often used: $params['data'] to add data attributes, $params['class'] to modify the className
*
*
* @param array $params this array holds the default values for $content and $args.
* @return $params the return array usually holds an innerHtml key that holds item specific markup.
*/
function editor_element( $params )
{
$params = parent::editor_element( $params );
$params['content'] = null; //remove to allow content elements
return $params;
}
/**
* Frontend Shortcode Handler
*
* @param array $atts array of attributes
* @param string $content text within enclosing form of shortcode element
* @param string $shortcodename the shortcode found, when == callback name
* @return string $output returns the modified html string
*/
function shortcode_handler( $atts, $content = '', $shortcodename = '', $meta = '' )
{
global $avia_config, $more;
extract( $atts );
$cards = [];
ob_start(); //start buffering the output instead of echoing it
$img = wp_get_attachment_image( $attachment, 'large' );
echo $this->render_module(ShortcodeHelper::avia_apply_autop( ShortcodeHelper::avia_remove_autop( $module_content ) ), $image_side, $module_image, $img);
$output = ob_get_clean();
avia_set_layout_array();
return $output;
}
function render_module($content,$image_side,$module_image, $image) {
$html = '';
$html .= '<div class="two-column-module '.$image_side.'-side">';
$html .= '<div class="image-container"><div class="module-image" style="background:url(\''.$module_image.'\'); background-repeat: no-repeat; background-position: center '.$image_side.'; background-size: cover"></div></div>';
$html .= '<div class="content-container">'.$content.'</div>';
return $html .= '</div>';
}
}
}
It also works properly with multiple tiny_mce boxes, too.
Note – this is only a problem when you create a custom shortcode element and give it an id of something other than ‘content’.