2
votes

I am having the following issues with rendering custom permalinks using WordPress, the Advanced Custom Fields post object field and Timber. I have posts and a custom post type photo galleries that are related and are connected by a link setup using the post object field attached to the story post. The rendered links are being displayed like this: http://example.com/photos/%locations%/bordeaux/. The %locations% segment should be replaced by world/france in this example.

The permalinks are properly rendered when access using the post's permalink (http://example.com/photos/world/france/bordeaux), attached to a WordPress menu or navigated to using the core search functionality.

The post object has the following parameters set:

  • Filter by Post Type: Photo Gallery (custom post type)
  • Return Format: Post Object

I have included my custom post type, taxonomy, and post_type_link functions below.

Custom post type (abbreviated)

function gerryfeehan_register_photos_post_type() {
  $args = [
    'label' => 'Photo Galleries',
    'labels' => [],
    'supports' => array(),
    'public' => true,
    'menu_position' => 5,
    'menu_icon' => 'dashicons-format-gallery',
    'capability_type' => 'post',
    'taxonomies' => [ 'locations', ],
    'has_archive' => true,
    'delete_with_user' => false,
    'rewrite' => [
        'slug' => 'photos/%locations%',
        'with_front' => false,
    ],
  ];
  register_post_type( 'photos', $args );
}
add_action( 'init', 'gerryfeehan_register_photos_post_type' );

Custom taxonomy (abbreviated)

function gerryfeehan_register_locations_taxonomy() {
  $args = [
    'labels' => [],
    'hierarchical' => true,
    'rewrite' => [
        'slug' => 'locations',
        'hierarchical' => true,
    ],
  ];
  register_taxonomy( 'locations', [ 'photos' ], $args );
}
add_action( 'init', 'gerryfeehan_register_locations_taxonomy' );

Post type link filter function

add_filter( 'post_type_link', 'gerryfeehan_post_type_link', 10, 2 );
function gerryfeehan_post_type_link( $post_link ) {
  $taxonomy = 'locations';
  $terms = get_the_terms( get_the_ID(), $taxonomy );
  $slug = [];
  // Warning: Invalid argument supplied for foreach()
  foreach ( $terms as $term ) {
    if ( $term->parent == 0 ) {
      array_unshift( $slug, sanitize_title_with_dashes( $term->name ) );
    } else {
      array_push( $slug, sanitize_title_with_dashes( $term->name ) );
    }
  }
  if ( ! empty( $slug ) ) {
    return str_replace( '%' . $taxonomy . '%' , join( '/', $slug ) , $post_link );
  }
  return $post_link;  
}

Timber get_field function

{{ story.get_field( 'associated_photo_gallery' ).link }}

Any suggestions on why the permalinks are not rendering correctly when being used by Advanced Custom Fields and Timber.

1
If you say "Any suggestions on why the permalinks are not rendering correctly", what is actually rendering? Do you get a wrong link or nothgin? What does {{ dump(story.get_field('associated_photo_gallery')) }} output? Is it an array that contains a link key?Gchtr
@Gchtr The following was displayed in the template using dump example.com/photos/%location%/bordeaux. There was a PHP warning related to the post_type_link function. I have updated my question to include those details. I am not sure if the two are related.Mike Hermary

1 Answers

0
votes

As far as I can see, your configuration for your custom permalink structure in register_post_type() looks fine.

The reason why you get an "Invalid argument supplied for foreach()" warning is because the post_type_link filter runs for every post type. But the locations taxonomy probably isn’t registered for every post type of your site and the get_the_terms() function returns false if there are no terms.

To fix this you should add a bailout that returns early when it’s not the photos post type. For that, you can use the $post parameter, that is provided as the second argument in the filter.

add_filter( 'post_type_link', 'gerryfeehan_post_type_link', 10, 2 );

function gerryfeehan_post_type_link( $post_link, $post ) {
    // Bail out if not photos post type.
    if ( 'photos' !== $post->post_type ) {
        return $post_link;
    }

    $taxonomy = 'locations';
    $terms    = get_the_terms( get_the_ID(), $taxonomy );
    $slug     = [];

    foreach ( $terms as $term ) {
        if ( $term->parent == 0 ) {
            array_unshift( $slug, sanitize_title_with_dashes( $term->name ) );
        } else {
            array_push( $slug, sanitize_title_with_dashes( $term->name ) );
        }
    }

    if ( ! empty( $slug ) ) {
        $post_link = str_replace( '%' . $taxonomy . '%', join( '/', $slug ), $post_link );
    }

    return $post_link;
}

Also, you need to make sure that you flush your permalinks by visiting the SettingsPermalinks page in the WordPress admin.