Update body class based on menu

As @CharlesClarkson has already explained, you cannot modify the page output with PHP after the output has been sent to the browser. Your menu certainly runs after body_class since the menu must run inside the <body> tag.

The only PHP solution I see would involve editing your theme templates in addition to the code above (with changes).

If you run wp_nav_menu before the <body> tag but use output buffering to capture the content instead of print it, what you are trying to do might work.

You would need to run your menu before the <body> tag, like this:

ob_start();
wp_nav_menu();
$my_captured_menu = ob_get_contents();
ob_end_clean();

In your function callback, instead of lines like this:

$body_class="has-submenu";

You would need this:

add_filter(
  'body_class',
  function($classes) {
    $classes[] = 'has-submenu'; // or 'is-submenu'
    return $classes;
  }
);

And of course, use echo $my_captured_menu wherever it needs to be printed.