How to properly save a WordPress option containing HTML code? - wordpress

Here's a screenshot of what the problem looks like:
And the HTML of that part of the WordPress options page looks like this:
So, in the WordPress admin area, I entered a piece of HTML code (to have a clickable link as the output on the frontend).
This was the code I had entered into that text input field on the backend:
<a title="Website Design London" href="../../website-design/">Website Design</a>
And while on the frontend that link is displaying OK, I'm seeing this mess (see screenshot) on the backend.
As far as I can tell the relevant PHP code is this:
$this->text(
'workdone',
esc_html__( 'Work done', 'mytheme' )
);
So, what is the proper way to save an option that contains HTML code?
And how can I fix the mess shown on the screenshot?

I had the same issue, and this code is working for me:
// render service label
public function render_service_label() {
$value = get_option( 'wbk_service_label', '' );
$value = htmlspecialchars( $value );
$html = '<input type="text" id="wbk_service_label" name="wbk_service_label" value="'.$value.'" >';
$html .= '<p class="description">' . __( 'Service label', 'wbk' ) . '</p>';
echo $html;
}
// validate service label
public function validate_service_label( $input ) {
$allowed_tags = array(
//formatting
'strong' => array(),
'em' => array(),
'b' => array(),
'i' => array(),
'br' => array(),
//links
'a' => array(
'href' => array(),
'class' => array()
),
//links
'p' => array(
'class' => array()
)
);
$input = wp_kses( $input, $allowed_tags );
return $input;
}
So, in the dashboard options page I use htmlspecialchars function
In frontend page I use like this:
$label = get_option( 'wbk_service_label', __( 'Select service', 'wbk' ) );

Related

Add attributes to ACF inner blocks

ACF has introduced inner block support which I'd like to use.
Via my block template, I have the following:
<?php
$allowed_blocks = array( 'core/heading', 'core/paragraph' );
echo '<InnerBlocks allowedBlocks="' . esc_attr( wp_json_encode( $allowed_blocks ) ) . '" />';
This limits the block editor to headings and paragraphs only.
Is it possible to add a class attribute to each heading and paragraph? For example, <p class="block__paragraph">.
I'm aware I can achieve this with str_replace but I wondered if there's a more efficient way to hook into InnerBlocks?
I'm also aware you can use templates, like so:
<?php
$template = array(
// Heading
array( 'core/heading', array(
'level' => 2,
'placeholder' => 'Add a Title',
'className' => 'block__heading',
) ),
// Paragrph
array( 'core/paragraph', array(
'className' => 'block__paragraph',
'placeholder' => 'Write your text.',
) ),
);
echo '<InnerBlocks template="' . esc_attr( wp_json_encode( $template ) ) . '" templateLock="false" />';
However, this limits the editor to a set number of blocks.

Display custom checkout field value on admin order detail section in Woocommerce

Hello I'm trying to display the custom checkout field in the admin order details page. My Custom field is Delivery Option and it allows the user to pick the to pick a value from checkbox. I use the code below following the similar topics about this, but it seems something is wrong with my code.
add_action( 'woocommerce_review_order_after_shipping', 'checkout_shipping_additional_field', 20 );
function checkout_shipping_additional_field()
{
$domain = 'wocommerce';
$default = 'option 1';
echo '<tr class="additional-shipping-fields"><th>' . __('Delivery Time', $domain) . '</th><td>';
// Add a custom checkbox field
woocommerce_form_field( 'custom_radio_field', array(
'type' => 'select',
'class' => array( 'form-row-wide' ),
'options' => array(
'option 1' => __('10:04 : 13:04 ', $domain),
),
'default' => $default,
), $default );
echo '</td></tr>';
}
//update order meta
add_action('woocommerce_checkout_update_order_meta', 'gon_update_order_meta_business_address');
function gon_update_order_meta_business_address( $order_id ) {
if ($_POST['custom_radio_field']) update_post_meta( $order_id, 'Business Address?',
esc_attr($_POST['custom_radio_field']));
}
// Display field value on the admin order edit page
add_action( 'woocommerce_admin_order_data_after_shipping_address', 'custom_checkout_field_display_admin_order_meta', 10, 1 );
function custom_checkout_field_display_admin_order_meta( $order ){
$delivery_time = get_post_meta( $order->get_id(), 'Delivery Time', true );
if( ! empty( $delivery_time ) )
echo '<p><strong>'.__('Delivery Time', 'woocommerce').': </strong> ' . $delivery_time . '</p>';
}
There is some mistakes, so I have revisited your code. I have also replaced some hooks. Try the following:
// HERE set your the options array for your select field.
function delivery_time_options(){
$domain = 'woocommerce';
return array(
'1' => __('10:04 : 13:04 ', $domain),
'2' => __('14:04 : 16:04 ', $domain), // <== Added for testing
);
}
// Display a custom select field after shipping total line
add_action( 'woocommerce_review_order_after_shipping', 'checkout_shipping_additional_field', 20 );
function checkout_shipping_additional_field(){
$domain = 'woocommerce';
echo '<tr class="additional-shipping-fields"><th>' . __('Delivery Time', $domain) . '</th><td>';
// Add a custom select field
woocommerce_form_field( 'delivery_time', array(
'type' => 'select',
'class' => array( 'form-row-wide' ),
'options' => delivery_time_options(),
), '' );
echo '</td></tr>';
}
// Save custom field as order meta data
add_action('woocommerce_checkout_create_order', 'save_custom_field_order_meta', 22, 2 );
function save_custom_field_order_meta( $order, $data ) {
if ( isset($_POST['delivery_time']) ) {
$options = delivery_time_options(); // Get select options array
$option_key = esc_attr($_POST['delivery_time']); // The selected key
$order->update_meta_data( '_delivery_time', $options[$option_key] ); // Save
}
}
// Display a custom field value on the admin order edit page
add_action( 'woocommerce_admin_order_data_after_shipping_address', 'display_custom_meta_data_in_backend_orders', 10, 1 );
function display_custom_meta_data_in_backend_orders( $order ){
$domain = 'woocommerce';
$delivery_time = $order->get_meta('_delivery_time');
if( ! empty( $delivery_time ) )
echo '<p><strong>'.__('Delivery Time', $domain).': </strong> ' . $delivery_time . '</p>';
}
Code goes in function.php file of your active child theme (or active theme). Tested and works.
Based on #LoicTheAztec answer, if you want multiple fields without re-writing the functions for every field (DRY), you can use this class (by adding it to your functions.php):
/**
* Add a custom field to the woocommerce checkout page
* https://stackoverflow.com/q/52098807/
*/
class WOO_Add_Checkout_Field
{
public function __construct($options)
{
$this->field_name = $options['field_name'];
$this->label = $options['label'];
$this->placeholder = $options['placeholder'];
$this->required = $options['required'];
if ($this->field_name && $this->label && $this->placeholder) {
add_action('woocommerce_after_order_notes', [$this, 'customise_checkout_field']);
add_action('woocommerce_checkout_update_order_meta', [$this, 'custom_checkout_field_update_order_meta'], 10, 1);
add_action('woocommerce_admin_order_data_after_billing_address', [$this, 'display_custom_field_on_order_edit_pages'], 10, 1);
} else {
die("Error in WOO_Add_Checkout_Field \$options: \n\n" . var_dump($options));
}
}
public function customise_checkout_field($checkout)
{
echo '<div id="customise_checkout_field">';
// echo '<h2>' . __('Heading') . '</h2>';
woocommerce_form_field($this->field_name, array(
'type' => 'text',
'class' => array(
'my-field-class form-row-wide'
),
'label' => $this->label,
'placeholder' => $this->placeholder,
'required' => $this->required,
), $checkout->get_value($this->field_name));
echo '</div>';
}
public function custom_checkout_field_update_order_meta($order_id)
{
if (!empty($_POST[$this->field_name]))
update_post_meta($order_id, $this->field_name, $_POST[$this->field_name]);
else
update_post_meta($order_id, $this->field_name, 0);
}
public function display_custom_field_on_order_edit_pages($order)
{
$field = $order->get_meta($this->field_name);
if (!empty($field)) {
echo '<p><strong style="display:block" title="' . $this->placeholder . '">' . $this->label . ': </strong><span>';
echo $field;
echo '</span></p>';
}
}
}
And use it as many times as you'd like:
$my_custom_field_1 = new WOO_Add_Checkout_Field([
'field_name' => 'my_custom_field_1',
'label' => __('My First Field'),
'placeholder' => __('Please write something in field 1...'),
'required' => false,
]);
$my_custom_field_2 = new WOO_Add_Checkout_Field([
'field_name' => 'my_custom_field_2',
'label' => __('My Second Field'),
'placeholder' => __('Please write something in field 2...'),
'required' => false,
]);
$my_custom_field_3 = new WOO_Add_Checkout_Field([
'field_name' => 'my_custom_field_3',
'label' => __('My Third Field'),
'placeholder' => __('Please write something in field 3...'),
'required' => false,
]);
// and so on...
Please note:
The custom field will show up in admin area ONLY if it was not sent empty
You can customize this code how you like

how to integrate redux framework metabox into custom post type?

I am using Redux Framework for theme development but I stuck on Metabox. I tried this doc https://docs.reduxframework.com/extensions/metaboxes/ but I didn't get any result.
I am unable to get the custom field on selected custom post type.
In extentions-init.php, I found:
// All extensions placed within the extensions directory will be auto-loaded for your Redux instance.
Redux::setExtensions( $opt_name, dirname( __FILE__ ) . '/extensions/' );
// Any custom extension configs should be placed within the configs folder.
if ( file_exists( dirname( __FILE__ ) . '/configs/' ) ) {
$files = glob( dirname( __FILE__ ) . '/configs/*.php' );
if ( ! empty( $files ) ) {
foreach ( $files as $file ) {
include $file;
}
}
}
It's clearly shows the custom metabox will be load from configs folder but it doesn't load.
Try something more like this... note that you need to add_action(
if ( !function_exists( "master_metaboxes_function" ) ){
function master_metaboxes_function($master_metaboxes) {
if ( file_exists( dirname( __FILE__ ) . '/configs/' ) ) {
$files = glob( dirname( __FILE__ ) . '/configs/*.php' );
if ( ! empty( $files ) ) {foreach ( $files as $file ) {include $file;} }
}
return $master_metaboxes;
}
// note this has to load AFTER the action loads...
add_action('redux/metaboxes/'.$YOUR_OPTION_ID.'/boxes', 'master_metaboxes_function');
}
Read this: https://github.com/reduxframework/redux-framework/issues/2605
As you can see in the documentation you need to hook into a filter to set your metaboxes, so in your plugin or theme, add this code :
(don't forget to replace {$redux_opt_name} with your unique vendor prefix/opt_name to prevent colissions with other plugins)
if ( !function_exists( "{%redux_opt_name%}_redux_add_metaboxes" ) ):
function {%redux_opt_name%}_redux_add_metaboxes($metaboxes) {
// Declare your sections
$boxSections = array();
$boxSections[] = array(
//'title' => __('General Settings', 'redux-framework-demo'),
//'icon' => 'el-icon-home', // Only used with metabox position normal or advanced
'fields' => array(
array(
'id' => 'sidebar',
//'title' => __( 'Sidebar', 'redux-framework-demo' ),
'desc' => 'Please select the sidebar you would like to display on this page. Note: You must first create the sidebar under Appearance > Widgets.',
'type' => 'select',
'data' => 'sidebars',
),
),
);
// Declare your metaboxes
$metaboxes = array();
$metaboxes[] = array(
'id' => 'sidebar',
'title' => __( 'Sidebar', 'fusion-framework' ),
'post_types' => array( 'page', 'post', 'acme_product' ),
//'page_template' => array('page-test.php'), // Visibility of box based on page template selector
//'post_format' => array('image'), // Visibility of box based on post format
'position' => 'side', // normal, advanced, side
'priority' => 'high', // high, core, default, low - Priorities of placement
'sections' => $boxSections,
);
return $metaboxes;
}
// Change {%redux_opt_name%} to your opt_name
add_filter("redux/metaboxes/{%redux_opt_name%}/boxes", "redux_add_metaboxes");
endif;

How to display custom shortcode single image in visual composer in wordpress?

I am trying to display custom fileds created by me in visual composer by using custom short codes. This custom short codes run fine when i am working with heading and text area_html ,but now i want to add single image in this sort code,but in result i am not getting image,it displays alt attribute and in back-end side i am showing my single image that stores in custom shortcode field. here i am including my code.
1) code for creating custom shortcode
vc_map( array(
'name' => __( 'trionn_header' ),
'base' => 'trionn_header',
'category' => ( 'trionn code' ),
'params' => array(
"type" => "attach_image",
"holder" => "img",
"class" => "",
"heading" => __( "Hintergrundbild", "my-text-domain" ),
"param_name" => "image_url",
"value" => __( "", "my-text-domain" ),
"description" => __( lade eins hoch", "my-text-domain" )
)
) );
2) code in separate function-name file
<?php
/* Ordered List shortcode */
if (!function_exists('trionn_header')) {
function trionn_header($atts, $content) {
$atts = shortcode_atts(
array(
'image_url' => ''
), $atts, 'trionn_header'
);
$imageSrc = wp_get_attachment_image_src($image_url, 'thumbnail');
$html = '<img src="' . $imageSrc[0] .'" alt="' . $atts['title'] . '"/>';
return $html;
}
add_shortcode('trionn_header', 'trionn_header');
}
I found solution for your question,try this in your code
In param tag write this array after main param attribute:
array(
"type" => "attach_image",
"heading" => "Image",
"param_name" => "image",
'admin_label' => true
)
paste below code in your function_name file:
<?php
// Trionn header custom code //
if (!function_exists('trionn_header')) {
function trionn_header($atts, $content = null) {
$args = array(
'title' => __( 'This is the custom shortcode' ),
'title_color' => '#000000',
'content' => 'your discrption here',
"image" => "",
);
extract(shortcode_atts($args, $atts));
//init variables
$html = "";
$image_classes = "";
$image_src = $image;
if (is_numeric($image)) {
$image_src = wp_get_attachment_url($image);
}
// generate output for heading and discription
$html = '<h1 class="trionn header ' . $atts['style']. '" style="color: ' . $atts['title_color'] . '">'. $atts['title'] . '</h1>'. "<div class=content>" . $content . "</div>";
// generate output for single image
$html .= "<img itemprop='image' class='{$image_classes}' src='{$image_src}' alt='' style='{$images_styles}' />";
return $html;
}
add_shortcode('trionn_header', 'trionn_header');
}
Enjoy, thank me later

Contact Form 7 and Custom post type

I want to use contact form 7 in Wordpress to build a order Form. I want the content of the order Form to be populated with content from a custom post type "trade Show Material" - The post type contains the fields "name" "number" "description" "photo" . The idea will be that each piece can be selected from the form . Can anyone offer the general direction for this? Should I perhaps be using another plugin entirely?
Maybe you can use the wpcf7_form_tag filter hook for this.
If you want to use a custom post type as the options of a dropdown (select) you can add something like the example below in your functions.php:
function dynamic_field_values ( $tag, $unused ) {
if ( $tag['name'] != 'your-field-name' )
return $tag;
$args = array (
'numberposts' => -1,
'post_type' => 'your-custom-post-type',
'orderby' => 'title',
'order' => 'ASC',
);
$custom_posts = get_posts($args);
if ( ! $custom_posts )
return $tag;
foreach ( $custom_posts as $custom_post ) {
$tag['raw_values'][] = $custom_post->post_title;
$tag['values'][] = $custom_post->post_title;
$tag['labels'][] = $custom_post->post_title;
}
return $tag;
}
add_filter( 'wpcf7_form_tag', 'dynamic_field_values', 10, 2);
In your form you can add the field:
[select* your-field-name include_blank]
In the example above the post_title is used in the options of the dropdown. You can add your own fields here (name, number, description, photo).
I do no think the wpcf7_form_tag works in the same way as vicente showed in his great answer before. It may have changed since 2015.
If you read here it explains how you need to use the wpcf7_form_tag: https://contactform7.com/2015/01/10/adding-a-custom-form-tag/
With that in mind along with this other post from Contact Form 7: https://contactform7.com/2015/02/27/using-values-from-a-form-tag/#more-13351
I came up with this code to create a custom dropdown list for a custom post type that I have.
add_action( 'wpcf7_init', 'custom_add_form_tag_customlist' );
function custom_add_form_tag_customlist() {
wpcf7_add_form_tag( array( 'customlist', 'customlist*' ),
'custom_customlist_form_tag_handler', true );
}
function custom_customlist_form_tag_handler( $tag ) {
$tag = new WPCF7_FormTag( $tag );
if ( empty( $tag->name ) ) {
return '';
}
$customlist = '';
$query = new WP_Query(array(
'post_type' => 'CUSTOM POST TYPE HERE',
'post_status' => 'publish',
'posts_per_page' => -1,
'orderby' => 'title',
'order' => 'ASC',
));
while ($query->have_posts()) {
$query->the_post();
$post_title = get_the_title();
$customlist .= sprintf( '<option value="%1$s">%2$s</option>',
esc_html( $post_title ), esc_html( $post_title ) );
}
wp_reset_query();
$customlist = sprintf(
'<select name="%1$s" id="%2$s">%3$s</select>', $tag->name,
$tag->name . '-options',
$customlist );
return $customlist;
}
Then you use the tag in contact form 7 like this.
[customlist your-field-name]
Hopefully this helps someone else who was looking for a way to do this like I was.
You could alter it to get any information you need from the custom post type.
It does not have any validation though.
Clyde Thomas code still works nice, thanks !
In my case I need the data from a plugin instead of a post so I've modified the code removing the WP_query and the while
global $wpdb;
$result = $wpdb->get_results("SELECT title FROM wp_asl_stores ORDER BY title ASC ");
foreach($result as $row) {
$customlist .= sprintf( '<option value="%1$s">%2$s</option>',
esc_html( $row->title ), esc_html( $row->title ) );
}

Resources