Completely custom wordpress menus

One can say a lot of bad things about PHP and Wordpress. But to be honest, I'm mostly grateful to these technologies for introducing me to coding. And grateful to the community around it for making it more or less easy to build stuff without actually knowing any code.

And Wordpress, for all the slack it gets, is still the most established CMS. Which is still why, for one off projects (like the future customer-facing site for rainforest) I'll take to wordpress.

One thing that I run into a lot is how little control you have over printing your menu, so I wrote a bunch of functions (omg functional php) to gain full control over my menus.

Like many others, I want to render child menu items in a dropdown extending from its parent item, so my html would look something like this:

<nav>
  <ul>
    <li><a href="...">Home</a></li>
    <li><a href="...">About</a></li>
    <li>
      <a href="...">Features</a>
      <ul>
        <li><a href="...">Feature 1</a></li>
        <li><a href="...">Feature 2</a></li>
        <li><a href="...">Feature 3</a></li>
      </ul>
    </li>
  </ul>
</nav>

To render this within Wordpress, first, we need to get all the menu items for a specific menu, we can do that with the gloriously named wordpress method: wp_get_nav_menu_items, like this:

<?php

$menu_items = wp_get_nav_menu_items('my-menu');

This will give us a list of all the menu items in it, including child menu items. That's not terribly useful, because as you can see above, the structure of the menu is a tree, not a flat list. It'll be easier if thd datastructure reflects the way it is represented, in a tree. So to enable us to render this menu, we need to take those menu items and build a tree.

And here's the first time that I write a recursive function in php. This function will take a bunch of items, loop over them and attach any children of this menu item to the ->children attribute.

<?php

function build_tree_menu($items, $tree = null) {
  if(!isset($tree)) {
    $tree = (object) [ 'children' => [] ];
  } else if (!isset($tree->children)) {
    $tree->children = [];
  }
  foreach ($items as $index => $item) {
    if(isset($tree->ID) == false && $item->menu_item_parent == 0 ||
      (isset($tree->ID) && $item->menu_item_parent == $tree->ID)) {
      array_splice($items, $index, 1);
      build_tree_menu($items, $item);
      array_push($tree->children, $item);
    }
  }
  return $tree;
}

When you run a menu item list through this function you end up with a datastructure which looks like this:

menu_item
menu_item
menu_item
  children
    menu_item
    menu_item

Now that we have a tree structure, we can render the menu, recursively. Because I love small functions I have three functions for this, although one could totally have two instead:

One to render the menu

<?php

function print_menu($tree) {
  if(isset($tree->children) && count($tree->children) > 0) {
    return '<ul>' . print_menu_nodes($tree->children) . '</ul>';
  }
}

One to render the menu nodes

<?php

function print_menu_nodes($items) {
  return join(array_map('print_menu_node', $items), '');
}

And one to render an individual menu node, which then calls print_menu again if it has children. As you can see I'm using the do_shortcode method so I can use shortcodes in menu descriptions.

<?php

function print_menu_node($item) {
  return '<li>' . 
    '<a ' .  'href="' .  $item->url .  '">' . 
    do_shortcode($item->title) . 
    '</a>' .  
    print_menu($item) . 
    '</li>';
}

Then I call my functions like this wherever I want to print a custom menu:

 <?php echo print_menu(build_tree_menu(wp_get_nav_menu_items('left-header-menu')));?>

So just to wrap this up, all you need to stick these functions into your functions.php:

<?php

function build_tree_menu($items, $tree = null) {
  if(!isset($tree)) {
    $tree = (object) [ 'children' => [] ];
  } else if (!isset($tree->children)) {
    $tree->children = [];
  }
  foreach ($items as $index => $item) {
    if(isset($tree->ID) == false && $item->menu_item_parent == 0 ||
      (isset($tree->ID) && $item->menu_item_parent == $tree->ID)) {
      array_splice($items, $index, 1);
      build_tree_menu($items, $item);
      array_push($tree->children, $item);
    }
  }
  return $tree;
}

function print_menu($tree) {
  if(isset($tree->children) && count($tree->children) > 0) {
    return '<ul>' . print_menu_nodes($tree->children) . '</ul>';
  }
}

function print_menu_node($item) {
  return '<li>' . 
    '<a ' .  'href="' .  $item->url .  '">' . 
    do_shortcode($item->title) . 
    '</a>' .  
    print_menu($item) . 
    '</li>';
}

function print_menu_nodes($items) {
  return join(array_map('print_menu_node', $items), '');
}

and then print your menu like this:

 <?php echo print_menu(build_tree_menu(wp_get_nav_menu_items('left-header-menu')));?>

Stubbing Grape Helpers

At rainforest we use rspec for testing. Our API layer is using Grape. Both projects have their ups and downs.

I'm still pretty new to ruby and the tooling you have in Ruby. Today I was stuck for a couple of hours because I wanted to stub an endpoint helper. I'm writing this down here for my own sanity and also, in case anybody else is looking for a solution to the same problem. So here you go:

describe MyAPI do
  context 'with a logged in user' do
    before do
      Grape::Endpoint.before_each do |endpoint|
        endpoint.stub(:current_user).and_return mock(:User, name: "Bob Example")
      end
    end

What we're doing here is we're using the static before_each method of Grape::Endpoint to stub out the :current_user helper that belongs to the scope of this endpoint.

This will affect every Endpoint that gets instantiated from here on out, so next we need to clean up after the lifecycle of this describe block has ended with rspecs after method:

    after { Grape::Endpoint.before_each nil }

Once that's done you can safely assume that inside this block, the helper will be stubbed:

    it "works" do
      get "/my/protected/endpoint"
      expect(response.status).to eq 200
    end
  end
end

Here is the code example in its entirety:

describe MyAPI do

  context 'with a logged in user' do
    before do
      Grape::Endpoint.before_each do |endpoint|
        endpoint.stub(:current_user).and_return mock(:User, name: "Bob Example")
      end
    end

    after { Grape::Endpoint.before_each nil }

    it "works" do
      get "/my/protected/endpoint"
      expect(response.status).to eq 200
    end
  end
end

And here's the original source of this information. Thanks to my friend Jonathan at Rainforest who pointed me in the right direction!

Error handling with async await

I'm playing around with async await lately to refactor our frontend data fetching layer. Naturally I wondered how I'm supposed to catch errors with async await.

It's surprisingly straight fowrward: Just use a try catch block.

Say I have a function that returns a promise which errors (Like a failed http request for example).

var asyncError = function(){
  return new Promise(function(resolve, reject){
    reject('boom');
  });
}

All I need to do is wrap the await statement in a try catch block:

(async function(){
  try{
    return await asyncError();  
  }catch(err){
    console.log('Oh my god there\'s an error', err);
  }
}());

It works just like you'd expect.

I love the async await spec, it's so powerful yet it's such a minimal addition to the JavaScript syntax. You might or might not be aware that async await spec comes from c#, in fact it's almost identical. Nod of respect to Microsoft!

I'm going to blog, for realz this time.

I must have written this type of blog post about 10 times or so. But seriously, this time I'm doing this for real. The blogging thing.

Cheers

J