SearchWP Results In WooCommerce Product & Variation REST API Search

There’s a super nifty extension out there to give SearchWP it’s own REST API endpoint and it’s super useful! It’s made by my good friends at Caldera Forms and it may just solve your needs.  But it wasn’t helping me solve a problem I had.  On a project I have a very customized hooked into and filtered situation going on with the WooCommerce products endpoint on the API.  I didn’t want to refactor to work with that plugin so I needed to get results going into the primary products endpoint we are already using.

?search=keyword

To use the default WordPress search functionality in an API endpoint you tack on ?search=keyword.  This is cool and all but we are implementing SearchWP.  SearchWP works by intercepting WP_Query when it’s got the ‘is_search’ set.  It then does it’s own thing and returns the results.

The issue is, it doesn’t intercept when doing a search through the REST API.  Why? I forgot, I dug through code for hours and figured it out but I can’t remember or sum up the reason so I’m just going to give my solution.

Pass Along IDs From SWP_Query

First thing you will want to do is hook into pre_get_posts and inject SWP_Query search results into the query’s ‘post__in’ parameter.  You need to also tell the query it’s not a search and be sure you are even in the right place to be doing this.  Here’s a quick gist

Order By Post__In

We can’t just let this go and it will work.  The query may still try to order by something other than the result of IDs we got from SearchWP.  So we need to hook into rest_{post_type}_query.  Here’s the gist of that.

Code Sample: Keep GIF Animation When Adding Media to Post Content in WordPress

When you upload an animated GIF to WordPress, or well any sort of image file, WordPress will upload the full size then resize to an array of different settings for thumbnails and medium sizes.  The issue is when it is an animated GIF the resized items are just a still of the first frame.  WordPress doesn’t have a GIF processor for rebuilding each frame at different sizes.

There is a plugin out there, it’s a bit outdated but might still do the trick.  If you aren’t planning on having hundreds of gifs slowing down your site then this code snippet will force all gifs to load their full size image when using the “Add Media” button.  You can then resize it with your mouse in place.

Remove Catalog Visibility Hidden Products In WooCommerce From Search & WP REST API Results

Woo doesn’t filter out products with hidden catalog visibility outside of main shop loop. This is important to remember when using the REST API for front end display or general search results. This code snippet will keep them from showing outside of the admin.

Turn Off Localization Temporarily in WooCommerce

I’m working on a site that’s in Japanese.  It’s a huge WooCommerce shop and they have a lot of custom meta fields we built for the English version of things.  Customers have their first and last name in my account and also fields we made for English First Name and English Last Name.

On the Addresses endpoint of WooCommerce’s “My Account” section we wanted to display the names/addresses in both Japanese and English.  This seemed easy except the Japanese state name that’s generated by Woo was being translated in the ‘woocommerce’ text domain.  The work-around was to unload the text domain, reload the countries/states instance with the data, get our state then reload the text domain.  This snippet did the trick:

WooCommerce: Add Fee To Order During Checkout If Cash On Delivery Or Any Other Reason/Gateway

Recently I was tasked with adding a field to the cash on delivery gateway in WooCommerce.  They wanted a field they could put in a dollar amount that would be tacked on as a fee to orders using that gateway.  Seemed simple enough with some googling but took a bit longer to tweak and get functioning correctly.

Add Field to Cash On Delivery Gateway

Adding fields in WooCommerce to its forms is pretty straight forward.  You hook into the WC Settings API and adjust them using this hook:

add_filter( 'woocommerce_settings_api_form_fields_<id>', function( $form_fields ) { return $form_fields; } );

Replace <id> with the id of the form.  In this case it’s “cod” for the Cash on Delivery form. In your hooked function you can manipulate the form fields array as needed.  For my case I just needed to add a field at the end for a fee so I do this:

Add Fee To The Order

Now that we have a fee set we need to hook into the checkout process.  For this I use the action “woocommerce_checkout_create_order” to manipulate the order right before it’s saved.  In WooCommerce 3.0 and over you no longer use the add_fee() function but instead create a line item fee object and add that to the order.  Here’s how I did what I needed:

SUPER IMPORTANT

Notice the add_item( $item ) call to place it in the order.  If that’s all you do then you will see the fee on the order but the order total won’t include it.  You need to make sure you run the order’s calculate_totals() function after adding the item.

Creating a Custom or Extended Gravity Forms Field with Multiple Inputs

I’m building a site for a Japanese company.  They need a Gravity Forms address field with a different order.  I spent a BOATLOAD of time trying to get this working and I finally did.  Here’s some details.

Extending Address Field

I started by extending the address field.  Simple enough.  Made some tweaks to the get_field_input() function to reorganize.  Made sure all other functions that used the .1, .2, etc. id’s for the inputs inside the field were updated in my field class.

After some trial and error with those I got the form field to be in the admin so I could add it to a form.  Awesome! Went to the front and there’s my new beautiful field.  But no matter how hard I tried it would not save any of the data.

I searched and searched through all the hooks I could find related to this.  I almost gave up but then I found a comment that said something about default inputs were loaded in js.php file.

JS.PHP

In the root directory of Gravity Forms is a file named js.php.  This file runs a switch case on different field types and populates some data.  If you look towards the bottom around line 838 at the writing of this post you will see:

<?php do_action( 'gform_editor_js_set_default_values' ); ?>

Right there you need to hook in your own default settings with field.inputs defined.  That’s about it! I just copied the info they had for the address field, tweaked it to match my class’s data and voila.

WordPress phpinfo() Version 16.3 – Click To Copy Plain Text

I’ve just released the latest version of my plugin to the WordPress repo.  You can now simply click a button to have a plain text version of the information copied to your clip board.  Paste into an email or support forum with ease and no crazy html or code getting included.

WordPress phpinfo()

Simple Custom Settings Fields for Give WP Donations Plugin

My previous post about Give was an intro to building a payment gateway for the plugin.  If you’ve built extensions for Give or are starting to then you’ve probably run into the settings fields API for adding a variety of inputs.  The options are limited and there are often times a need for custom fields.

How Give’s Settings Fields Work

In the class file class-admin-settings.php located in give/includes/admin/ the function output_fields handles displaying different types of fields registered.  If you are here you probably know the standard format for adding a settings field in your code:

settings[] = [
   'name'    => __( 'Select an Option', 'my-text-domain' ),
   'desc'    => '',
   'id'      => 'select_box_1',
   'type'    => 'select',
   'options' => [ 'op1' => 'Option 1', 'op2' => 'Option 2' ],
]

That adds a select field with a couple options.

As you add settings to an array they will be displayed in the same order in a Give formatted html table.  It appears they were using CMB2 but have since deprecated it.  I’m not 100% sure but there are remnants of it in the plugin.

Creating A Custom Field

Within the output_fields function I mentioned above there is a switch statement on the field type.  This goes through all the type options default in Give and outputs the field content based on type.  After all the case type options the default is a sweet do_action( ‘give_admin_field_’ . $value[‘type’], $value, $option_value );  This is how you do what you want to do with a custom field.

One thing I really needed when building an extension was a way to have inter-woven sub headers for form options.  I could not find a way to just output a title.  The type field title that’s default to Give outputs the top of a table with it as it’s meant to be, that’s right, at the top lol.

Let’s start with an example of creating a simple sub title output.

Remember, the form settings fields are all in a table so you need to use a table row to output your field.  Now we can add this subtitle between fields by using:

$settings[] = [
   'id'   => 'my_settings_subheader_one',
   'name' => 'Custom Sub Header Section',
   'type' => 'my_custom_subtitle',
];

Voila! We have a custom field in Give settings.  The type is set to what comes after give_admin_field_ in the add_action of our sample.

Custom Give Settings Fields Subheader and HR
Here I have two custom fields, a subheader field and a horizontal rule field

Saving Custom Field Data

Saving is pretty straight forward as well.  The example below is kind of pointless as Give already has a text box type but it shows how you’d go about saving your data in a custom field.

The key is figuring out how to structure your action’s name.  Give uses the settings page followed by _save_ followed by the tab you are on.  Here’s their documentation on it followed by an example.

/**
 * Trigger Action.
 *
 * Note: action dynamically fire on basis of setting page slug and current tab.
 * For example: if you register a setting page with give-settings menu slug and general current tab name
 *              then action will be give-settings_save_general
 *
 * @since 1.8
 */
do_action( self::$setting_filter_prefix . '_save_' . $current_tab );