Saved options array data randomly disappearing - wordpress

Not a Wordpress guru. I have inherited a small simple plugin that allows a user to upload an image, which then gets added to an array, and then you can add / edit array values for that image (title, description, etc). The issue I am having is it works great for awhile, then suddenly the form stops saving values to the option_value in the db. This could occur after 10-15 entries. I have verified that the payload being sent to options.php is correct.
Why does this plugin randomly stop saving data to the table?
I have registered the options array
$djwp_images = get_option('djwp_images');
add_action('admin_init', 'djwp_register_settings');
function djwp_register_settings() {
register_setting('djwp_images', 'djwp_images');
register_setting('djwp_settings', 'djwp_settings');
}
A single example shown below of how it iterates through the array for the form.
<form class="djform" method="post" action="options.php">
<?php foreach ($djwp_images as $id => $data) { ?>
// Single example shows how and array is used to input values
<input type="hidden" name="djwp_images[<?= $id; ?>][file_url]"
value="<?= $file_url ?>"/>
<? } ?>
<?= submit_button(); ?>
</form>
Full source code in pastebin
Using wordpress: 4.9.8

The problem is not directly related to WP. The problem is that on each loop (in for) it outputs about 20 inputs. In sum, it outputs hundreds of inputs, and you have to increase the amount of input_vars on your server. Either insert this in top of your functions.php, it should solve:
ini_set('max_input_vars', 3000);
ini_set('post_max_size', '128M');
or update those values in your server's php.ini (and restart server)

Related

Wordpress Shortcode Output Buffering Renders Content When Saving Post in WP Admin

I have a WP shortcode that is giving me problems.
Basically, the shortcode just pulls content from another post using a couple of parameters. It then loads up a partial template.
The problem occurs in WP Admin when saving the page that contains the shortcode. When saving the page updates do in fact save correctly but the resulting page is a page that outputs the contents of the shortcode.
I'm using output buffering around get_template_part() for two reasons: 1. So I only have one instance of the template in my code - and - 2. Because the template is actually pretty substantial and appending all of it to an output variable would be a daunting task.
The shortcode works fine in every way except when saving the page.
Here is a video demonstrating the issue:
https://www.awesomescreenshot.com/video/1146323?key=103ae00d841b47cee8a902eb18c8988a
Here is my code:
function get_main_page_content( $atts ) {
$main_page_id = $atts['main_page_id'];
$section = $atts['section'];
$people_display_option = $atts['people_display_option'];
$GLOBALS['sc_display_option'] = $people_display_option;
ob_start();
if(have_rows('flexible_content', $main_page_id)):
while(have_rows('flexible_content', $main_page_id)): the_row();
if ( $section == 'agenda' ) {
get_template_part('partials/agenda');
}
if ( $section == 'people_cards' ) {
get_template_part('partials/people-cards');
}
endwhile;
endif;
ob_end_flush();
$output = ob_get_contents();
ob_end_clean();
return $output;
}
add_shortcode('get_main_page_content', 'get_main_page_content');
It looks to me like ob_end_flush() is not needed and is redundant. That might be causing the OB to send twice, resulting in that code on your screen.
I'd be curious if your problem persists if you drop that line. Also, for a very simplified version of your exact usecase, check this blog post:
https://konstantin.blog/2013/get_template_part-within-shortcodes

How to get a Product Variation Custom Field to work along other plugins?

I get this code (see below) to create a Product Variation Custom Field. It works just fine. Now I need to use the WP All Import Pro plugin to import Products from a csv file. This plugin allow to create the importation task by mapping the information in the csv to the fields of Product and Product Variation.
Problem: thing is that the new created Product Variation Custom Field is not visible for the WP All Import plugin. I mean, this new field is not listed when I do the mapping of the data be imported.
My assumption is that this code fails to create some data in the database to make this field available for other module.
How can I get this to work properly
I also attached a capture of the WP All Import page where the field should be visible.
/*******************************
add custom fields to product variations
*********************************/
// regular variable products
add_action( 'woocommerce_product_after_variable_attributes', 'add_to_variations_metabox', 10, 3 );
add_action( 'woocommerce_save_product_variation', 'save_product_variation', 20, 2 );
/*
* Add new inputs to each variation
*
* #param string $loop
* #param array $variation_data
* #return print HTML
*/
function add_to_variations_metabox( $loop, $variation_data, $variation ){
$custom = get_post_meta( $variation->ID, '_custom', true ); ?>
<div class="variable_custom_field">
<p class="form-row form-row-first">
<label><?php echo __( 'MY CUSTOM FIELD:', 'plugin_textdomain' ); ?></label>
<input type="text" size="5" name="variation_custom_data[<?php echo $loop; ?>]" value="<?php echo esc_attr( $custom ); ?>" />
</p>
</div>
<?php
}
/*
* Save extra meta info for variable products
*
* #param int $variation_id
* #param int $i
* return void
*/
function save_product_variation( $variation_id, $i ){
// save custom data
if ( isset( $_POST['variation_custom_data'][$i] ) ) {
// sanitize data in way that makes sense for your data type
$custom_data = ( trim( $_POST['variation_custom_data'][$i] ) === '' ) ? '' : sanitize_title( $_POST['variation_custom_data'][$i] );
update_post_meta( $variation_id, '_custom', $custom_data );
}
}
WP ALL IMPORT has this section coded into their files. They have not provide any hook or filter to add fields to this section.
The most important thing here is that WP ALL IMPORT has thought is like this :
As all the Meta for a particular variation is added finally to the post meta table. Which will be retrieved as by get_post_meta. Just like the custom fields. So in order to attach meta to the variation, you can just another Custom Fields with the Name as the name which the actual meta is stored with and with the value you want the variation to be. Just check the image attached. Refer - http://www.wpallimport.com/documentation/custom-fields/theme-plugin-fields/
I know this question was asked almost a year ago but I have been trying to figure out this exact issue out for quite some time now. But in the end I managed to find a workaround that at least will allow you to get that data into the variation instead of the main parent product:
1) In the WpAllImport Wordpress Addon you will be able to see a "variations" tab as shown in your screenshot. Click on this.
2) On this page you will once again not be able to see any custom fields you have made for variations HOWEVER there is a product attributes section.
3) If you add your variation as an attribute and uncheck "Show in variations" and "Taxonomy" and "Is Visible" then you can store your data in an attribute.
4) After the import you should be able to see you data in the attribute, if you know some programming you can even write a script to then loop through all variations and copy this data over to a custom field.
I know it's not much, but for my purposes I was at least able to save the data in the variation which I then used late in a product export plugin.
Hope that helps!
Though this question was initially asked 2 years ago. I found a solution in 2020. I hope this will help anyone who's still looking for a solution.
Please go to All Products and at the top where it says Add New Product you should see two more buttons "Import" and "Export". Click on Export and you will see an option of checkbox "Yes, export all custom meta" Please check this potion and all your custom fields even in variations will be exported.
Thanks

Woocommerce add_to_cart hook empties cart

I'm using the woocommerce_add_to_cart action hook like so:
add_action('woocommerce_add_to_cart', 'display_more_modal', 10, 6);
function display_more_modal( $cart_item_key, $product_id, $quantity, $variation_id, $variation, $cart_item_data ) {
echo "<h1>Test Title here...</h1>";
//or
?>
<h1>More text here</h1>
<?php
}
I have found that if I echo out HTML or output HTML, as illustrated above, it removes all items from the cart, once I go the cart to view what I have added.
Could you some illustrate what I am possibly doing wrong? I have a suspicion that I have to return a value instead of echoing it.
If this is the case, please help as to how I can echo out HTML when a user adds a product to the cart. This HTML will be a popup with related products. Thank you.
I figured that some hooks within Wordpress don't like echoing anything out. I'm not sure how hard & fast this rule is but I remember it generally tends to be bad practice to echo anything out within functions. Instead they should return something. I simply created the product which was created and returned that. In the view file I created an if statement which outputs the html for the modal if a product exists. That seems to have fixed it.

Add custom product field on quick edit option on the product listing of a woocommerce site

How can I add custom product field/s on quick edit screen on the product listing of a woocommerce store?
I am not really sure if this is the best way to do it, but it works great for me
Basically my general goal is to add custom fields for a product, I managed to do it (Adding custom fields to the single product pages) with the help of these useful tuts.
http://www.remicorson.com/mastering-woocommerce-products-custom-fields/
http://www.remicorson.com/woocommerce-custom-fields-for-variations/
I recommend checking those links first before proceeding.
Now, what I wanted to do is to add those custom fields to the quick add option on the product listing.
That's where the resource get scarce.
Basically this is how I did it.
Add your custom field (the html forms) to the quick edit options.
I hooked into the 'woocommerce_product_quick_edit_end' action to accomplish this.
This hook is found on woocommerce->includes->admin->views->html-quick-edit-product.php on line 195
Save your custom field.
I hooked into the 'woocommerce_product_quick_edit_save' action to accomplish this.
This hook is found on woocommerce->includes->admin->class-wc-admin-post-types.php inside the 'quick_edit_save' function on line 929
The previous 2 steps does the trick, it does persist the values, however after updating the custom field via the quick edit option, the data is persisted on the backend, but is not populated to the custom field on the UI. That's why we need the 3rd step.
Add the custom field meta data inside the product listing column, then use js to extract the metadata out then populate it to the custom field
I hooked into the 'manage_product_posts_custom_column' action to add a custom HTML tags (div or whatever) to hold my custom field metadata
Then I used javascript to extract the data out from the meta data and populate it into the custom fields
Step 3 is just a copy of how WooCommerce does this process.
For referrence, take a look at function 'render_product_columns' of woocommerce->includes->admin->class-wc-admin-post-types.php
Also take a look at quick-edit.js located at woocommerce->assets->js->admin
Example Code:
Note that the code below is used for illustration and guide purposes, my actual code is quite long and complex.
Step 1:
add_action( 'woocommerce_product_quick_edit_end', function(){
/*
Notes:
Take a look at the name of the text field, '_custom_field_demo', that is the name of the custom field, basically its just a post meta
The value of the text field is blank, it is intentional
*/
?>
<div class="custom_field_demo">
<label class="alignleft">
<div class="title"><?php _e('Custom Field Demo', 'woocommerce' ); ?></div>
<input type="text" name="_custom_field_demo" class="text" placeholder="<?php _e( 'Custom Field Demo', 'woocommerce' ); ?>" value="">
</label>
</div>
<?php
} );
Step 2:
add_action('woocommerce_product_quick_edit_save', function($product){
/*
Notes:
$_REQUEST['_custom_field_demo'] -> the custom field we added above
Only save custom fields on quick edit option on appropriate product types (simple, etc..)
Custom fields are just post meta
*/
if ( $product->is_type('simple') || $product->is_type('external') ) {
$post_id = $product->id;
if ( isset( $_REQUEST['_custom_field_demo'] ) ) {
$customFieldDemo = trim(esc_attr( $_REQUEST['_custom_field_demo'] ));
// Do sanitation and Validation here
update_post_meta( $post_id, '_custom_field_demo', wc_clean( $customFieldDemo ) );
}
}
}, 10, 1);
Step 3:
add_action( 'manage_product_posts_custom_column', function($column,$post_id){
/*
Notes:
The 99 is just my OCD in action, I just want to make sure this callback gets executed after WooCommerce's
*/
switch ( $column ) {
case 'name' :
?>
<div class="hidden custom_field_demo_inline" id="custom_field_demo_inline_<?php echo $post_id; ?>">
<div id="_custom_field_demo"><?php echo get_post_meta($post_id,'_custom_field_demo',true); ?></div>
</div>
<?php
break;
default :
break;
}
}, 99, 2);
The JS part
jQuery(function(){
jQuery('#the-list').on('click', '.editinline', function(){
/**
* Extract metadata and put it as the value for the custom field form
*/
inlineEditPost.revert();
var post_id = jQuery(this).closest('tr').attr('id');
post_id = post_id.replace("post-", "");
var $cfd_inline_data = jQuery('#custom_field_demo_inline_' + post_id),
$wc_inline_data = jQuery('#woocommerce_inline_' + post_id );
jQuery('input[name="_custom_field_demo"]', '.inline-edit-row').val($cfd_inline_data.find("#_custom_field_demo").text());
/**
* Only show custom field for appropriate types of products (simple)
*/
var product_type = $wc_inline_data.find('.product_type').text();
if (product_type=='simple' || product_type=='external') {
jQuery('.custom_field_demo', '.inline-edit-row').show();
} else {
jQuery('.custom_field_demo', '.inline-edit-row').hide();
}
});
});
Make sure to enqueue the script
Hope this helps anyone, again, I am not sure if this is the best way to do it, but upon examining WooCommerce source, it seems WooCommerce
doesn't provide a convenient hook to accomplish this task with ease (at least not yet)
If you have a better approach than this please share.

Wordpress: Add config option to all widget settings

In Wordpress, my goal is to be able to give a custom class to every widget that I put in the sidebar.
Preferably I would like to add this class in the widget settings of each widget. ALSO 3rd party widgets.
I was thinking of changing the classname, because the classname is already passed to the register_sidebar function (%2$s):
<?php
register_sidebar(array('before_widget' => '<aside id="%1$s" class="widget %2$s blue">'));
?>
Ofcourse I shouldn't change WP core code or 3rd party plugins. This means that I need to write a plugin that will hook into the widget configuration process.
I already found out that it's possible to modify all widgets forms, by hooking into action 'in_widget_form':
<?php
add_action('in_widget_form', 'teaserWidgetAddToForm');
function teaserWidgetAddToForm($widget_instance) {
?>
<label for="<?php echo $widget_instance->get_field_id('teaser-classname'); ?>">Custom classname(s):</label>
<input type="text" id="<?php echo $widget_instance->get_field_id('teaser-classname'); ?>" name="<?php echo $widget_instance->get_field_name('teaser-classname'); ?>">
<?php
}
?>
This data should be saved by the Widget super class, but how do you retrieve this data (so when opening the widget settings later shows what you filled in earlier)
And, this saved data should be put in the widget instance -how is this done? I guess by using something like:
<?php
$wp_registered_widgets[<widget_id>]['callback'][0]['widget_options']['classname'] = <chosen_class>;
?>
So basically I have 2 questions:
Am I using the proper way to address this problem (styling of individual widgets)
If so, how can I modify a widget instance to save and retrieve additional settings, without having to modify Wordpress or 3rd party Plugin source code.
By default each widget instance has a unique ID which can be used to style it.
In order to save data from fields added in an in_widget_form action, you need to also have a widget_update_callback filter.
function my_widget_update_callback($instance, $new_instance) {
$instance['my_classnames'] = $new_instance['my_classnames'];
return $instance;
}
To display the saved value in the form you'll need to first retrieve the instance settings.
function my_in_widget_form($instance) {
$settings = $instance->get_settings();
…
Finally, I think the simplest way to add your custom classes is in a widget_display_callback filter, which runs before a widget is displayed. You have to display the widget yourself because you can only return an instance from this filter, and instances do not control the widget CSS classes.
function my_widget_display_callback($instance, $widget, $args) {
if (!isset($instance['my_classnames'])) {
return $instance;
}
$widget_classname = $widget->widget_options['classname'];
$my_classnames = $instance['my_classnames'];
$args['before_widget'] = str_replace($widget_classname, "{$widget_classname} {$my_classnames}", $args['before_widget']);
$widget->widget($args, $instance);
return false;
}
See this article for more info on the available hooks related to widgets: http://shibashake.com/wordpress-theme/wordpress-widget-system

Resources