Right Way to Add New Walker to Sage 9

That was in reply to Right Way to Add New Walker to Sage 9, right? Running composer install in the theme doesn’t solve my problem.

Hard to help without anything to go off.

Please provide the exact code that you are using/changes that you have made to Sage.

Hi Ben! Thanks - will try.

I’m running Windows 10 with Trellis/Bedrock/Sage 9-beta.4, and Soil installed via composer and activated.

In sage/app/ I’ve added a file nav-foundation-walker.php with QWp6t’s Foundation.php walker. So the file looks like this:

<?php 
namespace App;

use Roots\Soil\Nav\NavWalker as SoilNavWalker;

/**
 * Foundation 6 Navigation Walker
 *
 * @author QWp6t
 * @license OSL-3.0
 * @see https://gist.github.com/QWp6t/8f94b7096bb0d3a72fedba68f73033a5
 */

class FoundationWalker extends SoilNavWalker
{
    public function __construct()
    {
        parent::__construct();
        remove_filter('nav_menu_css_class', [$this, 'cssClasses'], 10);
        add_filter('nav_menu_css_class', [$this, 'itemClasses'], 10, 4);
    }
    /**
     * @param string $output
     * @param int $depth
     * @param array $args
     * @SuppressWarnings(PHPMD.CamelCaseMethodName) This method overrides its parent
     * @SuppressWarnings(PHPMD.UnusedFormalParameter) This method overrides its parent
     */
    // @codingStandardsIgnoreLine
    public function start_lvl(&$output, $depth = 0, $args = [])
    {
        $output .= '<ul class="submenu menu" data-submenu>';
    }
    /**
     * @param $classes
     * @param $item
     * @param $args
     * @param $depth
     * @return array
     * @SuppressWarnings(PHPMD.UnusedFormalParameter) This method overrides its parent
     */
    public function itemClasses($classes, $item, /** @noinspection PhpUnusedParameterInspection */ $args, $depth)
    {
        return array_filter(array_map(function ($class) use ($depth) {
            switch ($class) {
                case 'menu-item-has-children':
                    return 'has-submenu';
                default:
                    return $class;
            }
        }, parent::cssClasses($classes, $item)));
    }
}

Then in sage/resources/functions.php I added nav-foundation-walker to the Sage required files:

/**
 * Sage required files
 *
 * The mapped array determines the code library included in your theme.
 * Add or remove files to the array as needed. Supports child theme overrides.
 */
array_map(function ($file) use ($sage_error) {
    $file = "../app/{$file}.php";
    if (!locate_template($file, true, true)) {
        $sage_error(sprintf(__('Error locating <code>%s</code> for inclusion.', 'sage'), $file), 'File not found');
    }
}, ['helpers', 'setup', 'filters', 'admin', 'nav-foundation-walker']);

When I load the site in a browser I get the error:

Fatal error: Class 'Roots\Soil\Nav\NavWalker' not found in /srv/www/test.com/current/web/app/themes/sage/app/nav-foundation-walker.php

How do I use Composer and autoloading so that Roots\Soil\Nav\Navwalker is available in nav-foundation.php?

I’ve tried modifying Soil’s composer.json file by adding:

"autoload": {
    "psr-4": {
      "Roots\\Soil\\Nav\\": "modules/"
    }
  },

And I’ve tried modifying Sage’s composer.json file by adding:

"autoload": {
    "psr-4": {
      "App\\": "app/",
      "Roots\\Soil\\Nav\\": "../../plugins/Soil/modules/"
    }
  },

Each time I ran composer update to create a new vendor/autoload_psr4.php file. I also tried something similar in Bedrock’s composer.json file. None of these worked. What am missing here?

1 Like

Any update on this? I’ve just updated from Sage 9 beta 3 (worked fine) to beta 4 and this kind of problems are popping up all over the place.

@krishaamer No fixes yet on my end. I assume I just need a better understanding of autoloading, but I haven’t had a chance to dig in to it. I did start reading a tutorial on autoloading by Alan Storm that could be helpful.

1 Like

I now have QWp6t’s Foundation.php walker working using psr-4 autloading, instead of by requiring the foundation walker file after the Soil plugin has loaded using after_setup_theme().

The problem is that Soil’s NavWalker class is in a file named nav-walker.php. According to the psr-4 spec #3.3 listed here:

“When loading a file that corresponds to a fully qualified class name, the terminating class name corresponds to a file name ending in .php. The file name MUST match the case of the terminating class name.”

So the nav-walker.php file name and NavWalker class name need to match.

I did the following:

  1. Changed the file name from nav-walker.php to NavWalker.php.

  2. Soil’s modules are loaded based on file name, so in Sage’s setup.php file I changed line 28 to add_theme_support('soil-NavWalker').

  3. Added the following to Bedrock’s composer.json file (multi-line code formatting isn’t working in ordered lists):

    “autoload”: {
    “psr-4”: {
    “Roots\Soil\Nav\”: “web/app/plugins/soil/modules/”
    }
    }

  4. Ran composer update and confirmed the mapping had been added to Bedrock’s /vendor/composer/autoload_psr4.php.

  5. Finally, in Sage’s functions.php file I removed the after_setup_theme() hook I had previously used to load the foundation walker file and instead added the file to Sage’s required files array:
    ['helpers', 'setup', 'filters', 'admin', 'theme-options', 'nav-foundation-walker']

And voila, it works!

It would be great if the Soil changes could be merged so that it can work with autoloading.

Merry Christmas! (if that’s your thing)

4 Likes