0

In my theme's theme file I'm using preprocess_node to create variables for a node based on the section of my site its in, and that's figured out by checking the path's alias.

So for example a path like: /events/this_is_my_node

It'll see that this node is in the events section of the site and the variables provided to the twig template facilitate theming the node page based on the section it's in.

Everything works great if the node and the node that's the section's landing page have their aliases generated, but if they don't, I get an error like:

UnexpectedValueException: External URLs do not have internal route parameters. in Drupal\Core\Url->getRouteParameters() (line 583 of core/lib/Drupal/Core/Url.php).

So basically I'm trying to figure out a conditional I can use so that I'm only getting Route parameters from a path it recognizes as being internal and should something go wrong and a path alias isn't set I don't get a WSOD.

I've tried using UrlHelper::isExternal but that doesn't seem to help as it just seems to look at the path structure to determine if its external or not vs actually check the page.

This is my code:

function THEME_preprocess_node(&$variables) {
  $route_name = \Drupal::routeMatch()->getRouteName();
  $variables['#cache']['contexts'][] = 'route.name.is_layout_builder_ui';
  $internal_path = \Drupal::service('path.current')->getPath();
  $current_path = \Drupal::service('path_alias.manager')->getAliasByPath($internal_path);
  $variables['current_path'] = $current_path;
  $variables['internal_path'] = $internal_path;
  $int_exp = explode("/", $current_path);
  $alias = \Drupal::service('path_alias.manager')->getPathByAlias($int_exp[1]);
  $is_layout = false;
  if ($route_name ) {
    $node = $variables['node'];
    // check if layout builder is active
    if (isset($int_exp[3])) {
      if ($int_exp[3] == 'layout' or $int_exp[1] == 'layout_builder')
      {
        $is_layout = true;
      }
    }

    if (isset($internal_path) && !$is_layout) {
      $params = Url::fromUri("internal:/" . $alias)->getRouteParameters();
      $entity_type = key($params);
      if (isset($entity_type)) {
        $node = \Drupal::entityTypeManager()->getStorage($entity_type)->load($params[$entity_type]);
        $variables['section_nid'] = $node->nid->value;
        $variables['is_site_section'] = false;
        if ($node->type->target_id == 'sections') {
          $variables['is_site_section'] = true;
          $variables['current_section'] = $node->field_section_machine_name->value;
          $variables['current_section_title'] = $node->title->value;
        }
      }
    }

  }
}
2
  • 2
    The code should be based on the route match, which you use only to determine whether a route name was matched, but you don't use the route name or the route parameters from there. You don't need to write code trying to match the current path again, it is already matched.
    – 4uk4
    Commented Jul 25, 2023 at 6:24
  • Truly, what returned by \Drupal::service('path_alias.manager')->getAliasByPath($internal_path) is a path alias, and what returned by \Drupal::service('path_alias.manager')->getPathByAlias($int_exp[1]) is the path matching the path alias. The code assigns the value returned by \Drupal::service('path_alias.manager')->getAliasByPath($internal_path) to $current_path, and the value returned from \Drupal::service('path_alias.manager')->getPathByAlias($int_exp[1]) to $alias.
    – apaderno
    Commented Jul 25, 2023 at 12:38

1 Answer 1

1

You should not check for internal. An url like internal:/robots.txt is internal, but it is no route and has no route parameters.

So before you do Url::getRouteParameters() you should check for Url::isRouted()

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.