google-code-export / wordpress-custom-content-type-manager

Automatically exported from code.google.com/p/wordpress-custom-content-type-manager
2 stars 1 forks source link

Custom post type archive - error in nav-menu-template.php #525

Open GoogleCodeExporter opened 9 years ago

GoogleCodeExporter commented 9 years ago
I created a custom post type called 'vehicle' using CCTM and copy/pasted 
archive.php to archive-vehicle.php but this has resulted in an error in my 
header:

Warning: in_array() expects parameter 2 to be array, null given in 
/home/.../public_html/wp-includes/nav-menu-template.php on line 439

I get the same error repeated for every main menu item (there are no submenus).

If I remove archive-vehicle.php and view the same posts using archive.php no 
errors appear.

**What steps will reproduce the problem? (Be *specific*)**
1. Create a hierarchical custom post type of e.g. 'vehicle'
2. Create an archive page for this post type e.g. archive-vehicle.php
3. View the archive page - error shows before every menu item is rendered.

I raised this as a question here:

http://wordpress.stackexchange.com/questions/115604/custom-post-type-archive-err
or-in-nav-menu-template-php#115619

and received an answer from chrisguitarguy which suggests this is due to a bug 
in the plugin.

Original issue reported on code.google.com by gpc...@gmail.com on 25 Sep 2013 at 2:36

GoogleCodeExporter commented 9 years ago
For completeness I'll add chrisguitarguy's answer here:

[quote
print_r($queried_object) right before line 439 generates the following - 
there's no 'ancestors' key
[/quote]

When you are on a post type archive calling get_queried_object (which the code 
probably does) or using WP_Query::$queried_object return the post type 
"object". All that is is the arguments with which the post type was registered.

The relevant bit of nav-menu-template.php in WordPress 3.6.

<?php
function _wp_menu_item_classes_by_context( &$menu_items ) {
    // ...
    foreach ( (array) $menu_items as $key => $parent_item ) {
        // ...
        if (
            isset( $parent_item->type ) &&
            (
                // ancestral post object
                (
                    'post_type' == $parent_item->type &&
                    ! empty( $queried_object->post_type ) &&
                    is_post_type_hierarchical( $queried_object->post_type ) &&
                    in_array( $parent_item->object_id, $queried_object->ancestors ) &&
                    $parent_item->object != $queried_object->ID
                ) ||

                // ancestral term
                (
                    'taxonomy' == $parent_item->type &&
                    isset( $possible_taxonomy_ancestors[ $parent_item->object ] ) &&
                    in_array( $parent_item->object_id, $possible_taxonomy_ancestors[ $parent_item->object ] ) &&
                    (
                        ! isset( $queried_object->term_id ) ||
                        $parent_item->object_id != $queried_object->term_id
                    )
                )
            )
        ) {
            $classes[] = empty( $queried_object->taxonomy ) ? 'current-' . $queried_object->post_type . '-ancestor' : 'current-' . $queried_object->taxonomy . '-ancestor';
        }
        // ...
    }
    // ...
}

This bit ! empty( $queried_object->post_type ) should evaluate to false on post 
type archives. Something is adding post type to the queried object. And by 
something I mean your plugin which is _doing_it_wrong. Take a look at 
CCTM::register_custom_post_types() and CCTM::$default_post_type_def.

Anything that get's passed into register_post_type is just stored as an 
argument in the post type globals array.

If I do this:

register_post_type('some_type', array('this_is_not_a_wp_arg' => true));

On archive-some_type.php I can check for this_is_not_a_wp_arg.

<?php
// archive-some_type.php
var_dump(get_queried_object()->this_is_not_a_wp_arg); // true

Because your plugin happens to put post_type into the arguments array, it 
causes WP to evaluate ! empty( $queried_object->post_type ) as true. This isn't 
an issue in archive.php because $query_object->post_type is empty. As it should 
be on any post type archive. Unfortunately the CCTM plugin author doesn't 
understand the consequences of passing a "reserved" word like post_type as an 
argument key. This is why prefixing things is important.

EDIT

A very hackish fix is to hook into init very late and loop through all the post 
types. If the post_type argument is set, remove it. This may break other things 
the plugin does in the admin area.

<?php
add_action('init', 'wpse115604_fix', 10000);
function wpse115604_fix()
{
   foreach (get_post_types(array(), 'objects') as $type) {
       if (isset($type->post_type)) {
           unset($type->post_type);
       }
   }
}

This would prevent you from having to edit the plugin itself. I would do the 
above, then report the issue to the plugin author. If/when it gets fixed in a 
future version, you'll be able to remove that code.

TL;DR: CCTM adds a key to registered post types named post_type is messes with 
the order of things and sets a sequence of errors in motion.

Original comment by gpc...@gmail.com on 25 Sep 2013 at 3:31

GoogleCodeExporter commented 9 years ago

Original comment by ever...@fireproofsocks.com on 25 Sep 2013 at 3:43