When Technologies Collide, part 2

Note: This is second instance that demonstrates how the features of different pieces of software can collide and not meet the needs of a website owner. It is a common occurrence in websites which use a multitude of pieces and parts from various sources. But, it happens in a completely custom system too, as new features are added, or features are changes to meet new needs.

WordPress database table. Posts, Pages, Media Library, etc. All these types of content are in the database.
THE TECHNOLOGies

Today, we had a technology collision. After a great deal of work on a new section of website posts, we found that a technology would not show what we wanted to show on the home page. Three technologies didn’t work together as expected:

  1. The WordPressk core
  2. Kahuna Theme
  3. Toolset Types
THE NEED

The client needs the Kahuna Featured Boxes on the home page to show a post from a Custom Post Type.

The relevant Technology Features

The WordPress core has Posts, Pages and the Media Library as default content types.

The template for lumber uses a custom post type for fields that are needed for lumber measurements.

Entries made in any of these goes creates a record in the post table.The first screenshot shows the post_type field on the posts in the database. WordPress also keeps track of each time you update a post or page as a “revision”. And, WordPress keeps track of every item you add to the Media Library and what type of media it is as an “attachment”. Although the actual media file is stored in the file structure, to work with WordPress, the media item must be listed in the database. Most WordPress sites only need a few Pages, so they don’t show up in the database as often. There are more Posts and Media Library entries.

The template for plywood uses a custom post type for fields that are needed for plywood measurements.

The WordPress core also allows developers to create Custom Post Types that have custom fields when a project needs additional or different specific fields than what the WordPress core offers. If you have a site with WooCommerce, you may have noticed that there is a new item in the menu called Products. This is a Custom Post Type.

I have several clients who use Custom Post Types with custom fields. For example, Goosebay Lumber uses Custom Post Types because Lumber and Plywood have different fields in how lumber and plywood are measured and priced. Besides through coding, Custom Post Types can be created through plugins, such as Toolset Types that create the code, based on entries in the pages the plugin adds to the WordPress dashboard. This allows the site owner to add and change fields without coding. But, it does take  some coding to have the fields show on the site.

The problem in this example comes from the fact that the Kahuna theme makes use of the designations in the post_type field in the WordPress database and only allows Posts to be added to the Feature Boxes under the banner on the home page, not Custom Post Types, even though they are in the same database table.

The reason Kahuna works this way is that Posts can be assigned to Categories. The Kahuna theme lets the developer assign posts from a specific category to show in the Feature Boxes. That allows the site owner to control which Posts show in those boxes and change them out, as needed. The irony is that Custom Post Types can have Categories too, but even if the Category matches, Custom Post Types just don’t pick up in the Feature Boxes. So, is it possible to tell the programming to look at both Posts and Custom Post Types?

How to Fix the Problem

Whenever a website has a database, information is copied from the database by a type of code called a query. The query home page Feature Box query in the Kahuna theme needs to be changed to include the Custom Post Types. With a child theme, that query can be changed without overwriting any of the parent theme code. The next step is to figure out where that code is in this particular child theme.

Kahuna Parent Theme Files Involved in the “Landing Page”

Here is where it helps to have a little knowledge of how WordPress themes work. There are several file names for a home page file in the theme: index.php, home.php, front-page.php. Then you have to trace the code from file to file to find where the query is.

  1. kahuna/front-page.php – if the WordPress site is set to have a Home Page as opposed to the latest blog posts, the kahuna/front-page.php file calls the function get_template_part() with this code:
    if ( $kahuna_landingpage )
    {
    get_template_part( apply_filters(‘kahuna_landingpage_main_template’, ‘content/landing-page’ ) );
    } else
    {
    kahuna_lpindex();
    }
  2. kahuna/content/landing-page.php – The code above sends you to this file. But this file just lines up the functions that make the landing page. The list could be reordered to rearrange the page. Note that the Kahuna theme has its own content folder. The code in this file calls the function: kahuna_lpboxes(). How can we find the function when there is no reference to a file? A site search could do that.
  3. kahuna/includes/landing-page.php – The search reveals the file that has the query. It’s always nice to see the WordPress core object: new WP_query(). Now the question is how to get that query to pull from both posts and the custom post type
    $custom_query = new WP_query();
    if ( ! empty( $options[‘kahuna_lpboxcat’ . $sid] ) ) $cat = $options[‘kahuna_lpboxcat’ . $sid]; else $cat = ”;$args = apply_filters( ‘kahuna_boxes_query_args’, array(
    ‘showposts’ => $options[‘kahuna_lpboxcount’ . $sid],
    ‘cat’ => cryout_localize_cat( $cat ),
    ‘ignore_sticky_posts’ => 1,
    ‘lang’ => cryout_localize_code()
    ), $options[‘kahuna_lpboxcat’ . $sid], $sid );
    $custom_query->query( $args );
  4. functions.php – this file in the child theme allows custom function work that is added to functions in the WordPress core and in the parent theme.
Finding a Coding Solution

The final line in File 3 $custom_query->query($args); is what sends a question to the database to pick up the data for the Feature Boxes. Either the query itself, or $args has to be changed to allow it to pick up the Custom Post Types.

Solutions to problems like this are often found in forums where developers help each other. This makes the process more efficient for all, as no developer can know everything about every technology. In a Google search, I found a StackOverflow question that is similar enough to this problem that it could hold part of the answer.

The question writer said, “I’m trying to create a plugin which adds a new custom post type and it should be shown at the same locations as a normal post (front page, archives etc.). ” I’m not trying to create a plugin like the writer of the original question, but I do want custom post types to be able to be shown on the front page. Part of the skill of using resources is to figure out which types of questions might hold the answer you need.

Looking at the answer, I see that it is not changing the functions in the theme, but adding to a function that is part of the WordPress core: pre_get_posts( ). All tracing through the Kahuna theme files did for me was to confirm that Kahuna uses new WP_query(); from the WordPress core. Because it does, the code below can work … but can it?

add_action('pre_get_posts', 'djg_includ_my_cpt_in_query', 99);
function djg_includ_my_cpt_in_query($query){

    if(is_home() && $query->is_main_query()) :              // Ensure you only alter your desired query

        $post_types = $query->get('post_type');             // Get the currnet post types in the query

        if(!is_array($post_types) && !empty($post_types))   // Check that the current posts types are stored as an array
            $post_types = explode(',', $post_types);

        if(empty($post_types))                              // If there are no post types defined, be sure to include posts so that they are not ignored
            $post_types[] = 'post';         
        $post_types[] = 'document';                         // Add your custom post type

        $post_types = array_map('trim', $post_types);       // Trim every element, just in case
        $post_types = array_filter($post_types);            // Remove any empty elements, just in case

        $query->set('post_type', $post_types);              // Add the updated list of post types to your query

    endif; 

    return $query;

}

 

I need to take into consideration that this post is from 2014. WordPress has changed significantly since then, so I need to check whether the functions are still valid and whether there are changes. I will do that by searching for the pre_get_posts function in WordPress.org. The search shows me that the function is still good! So, I will proceed.

Trying the Coding Solution

Since I already have a child theme started, the first thing I have to do is save the file /kahuna/includes/landing-page.php into the child theme. If I don’t have the includes folder, I need to add it to preserve the file structure.

Now, I have to be very careful about 2 things: 1) what to use of the code above, 2) where to put the code I add.

Step 1: Copy the code

First, I copy that code into the child theme’s functions.php file. There should already be a functions.php file because you have to add it to make the child theme.

ThenThere are updates and changes to be made. One important part of doing this type of work is to understand WordPress functions and to know what you need to know about each function.

Step 2: The function arguments are different

The code above has:
add_action(‘pre_get_posts’, ‘djg_includ_my_cpt_in_query’, 99);”
The code in WordPress.org has:
add_action( ‘pre_get_posts’, ‘your_function_name’ );

Step 3: Change the number of arguments

Function calls take arguments or parameters. You can tell what code is a function call because it has ( ). So, add_action( ) is a function call. The third item in the code from 2014: 99, is no longer part of the function.  Now there are only 2 arguments, the function name pre_get_posts and the function name that you add to your new code.

Step 4: Change the new function name to something readable

This is an awful function name: djg_includ_my_cpt_in_query. Cryptic function names are from a by-gone era of programming. Maintainability is the new ideal. So, I will name my function AddCustomPostTypesToQuery.

The introductory text to pre-get_posts( ) tells us quite a lot about how this function works and how to code for it, “This hook is called after the query variable object is created, but before the actual query is run. The pre_get_posts action gives developers access to the $query object by reference (any changes you make to $query are made directly to the original object – no return value is necessary).”

Step 5: Change the test in the if statement

The function is_home( ) doesn’t work. WordPress.org explains why. Instead, I need to use is_front_page( ). I added a test into the code to see what Post Types are being called. The menu shows the correct Post Type. The slider shows the correct Post Type, but the Feature Boxes show no Post Type.

Step 6: Add your custom post type

if(empty($post_types))
{
// If there are no post types defined, be sure to include posts so that they are not ignored
$post_types[] = ‘post’;
$post_types[] = ‘product-list’;
// Add your custom post type
}

I added this line: $post_types[] = ‘product-list’;

Now I can add a Product List post to the Feature Boxes category and it works!

 

 

Leave a Reply

Your email address will not be published. Required fields are marked *