0

I have the following two functions in my .theme file that I'm using to gleam various bits of information from both the path alias and internal URL of the page being viewed. They are:

function rtv_preprocess_block(&$variables) {
  $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 (isset($int_exp[3]) and $int_exp[3] == 'layout') {
    $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;
      }
    }
  }
}

function rtv_preprocess_node(&$variables) {
  $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 (isset($int_exp[3]) and $int_exp[3] == 'layout') {
    $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;
      }
    }
  }
}

While they work where I need them to, I'm having issues with errors related to the pages where the function is being run on a path that doesn't have an internal path... generally giving me an error that says "External URLs do not have internal route parameters."

You'll see in my above functions that I've been trying to set up various conditionals to try to avoid this error. I thought I had done so, but then I discovered that I was getting ajax errors when trying to use the Layout Builder that broke its functionality. I thought checking if the path had a third segment with "layout" in it that I could tell it not to fire the functions on the layout edit page, but it still is. Any thoughts on where my mistake is?

In addition, I'm open to recommendations on making these functions more streamline or perhaps merging them into a single function that works with both blocks and nodes.

More information: The site is broken up into sections and each section is defined by a node from a content type called "sections". The path aliases are setup so pages are domain.com/sectionname/pagename. These functions basically are creating some variables to be used in my twig templates so I can theme these different sections differently.

Here's the full ajax error:

Object { message: "\nAn AJAX HTTP error occurred.\nHTTP Result Code: 500\nDebugging information follows.\nPath: /layout_builder/update/block/overrides/node.3205/2/second/ce22e4bb-e72c-406e-a430-5b4a36267126?destination=/node/3205/layout&_wrapper_format=drupal_dialog.off_canvas&ajax_form=1\nStatusText: 500 Service unavailable (with message)\nResponseText: The website encountered an unexpected error. Please try again later.UnexpectedValueException: External URLs do not have internal route parameters. in Drupal\\Core\\Url->getRouteParameters() (line 583 of core/lib/Drupal/Core/Url.php). rtv_preprocess_block(Array, 'block', Array)\ncall_user_func_array('rtv_preprocess_block', Array) (Line: 287)\nDrupal\\Core\\Theme\\ThemeManager->render('block', Array) (Line: 433)\nDrupal\\Core\\Render\\Renderer->doRender(Array) (Line: 446)\nDrupal\\Core\\Render\\Renderer->doRender(Array, ) (Line: 204)\nDrupal\\Core\\Render\\Renderer->render(Array) (Line: 479)\nDrupal\\Core\\Template\\TwigExtension->escapeFilter(Object, Array, 'html', NULL, 1) (Line: 52)\n__TwigTemplate_3657feff99df006eb4f124e3a699561a084dfd8bb48a625bef56f6fce9484a7e->doDisplay(Array, Array) (Line: 405)\nTwig\\Template->displayWithErrorHandling(Array, Array) (Line: 378)\nTwig\\Template->display(Array) (Line: 390)\nTwig\\Template->render(Array) (Line: 55)\ntwig_render_template('core/themes/stable9/layouts/layout_discovery/onecol/layout--onecol.html.twig', Array) (Line: 384)\nDrupal\\Core\\Theme\\ThemeManager->render('layout__onecol', Array) (Line: 433)\nDrupal\\Core\\Render\\Renderer->doRender(Array) (Line: 446)\nDrupal\\Core\\Render\\Renderer->doRender(Array) (Line: 446)\nDrupal\\Core\\Render\\Renderer->doRender(Array) (Line: 446)\nDrupal\\Core\\Render\\Renderer->doRender(Array, 1) (Line: 204)\nDrupal\\Core\\Render\\Renderer->render(Array, 1) (Line: 148)\nDrupal\\Core\\Render\\Renderer->Drupal\\Core\\Render\\{closure}() (Line: 580)\nDrupal\\Core\\Render\\Renderer->executeInRenderContext(Object, Object) (Line: 149)\nDrupal\\Core\\Render\\Renderer->renderRoot(Array) (Line: 36)\nDrupal\\Core\\Ajax\\InsertCommand->getRenderedContent() (Line: 31)\nDrupal\\Core\\Ajax\\ReplaceCommand->render() (Line: 43)\nDrupal\\Core\\Ajax\\AjaxResponse->addCommand(Object) (Line: 47)\nDrupal\\layout_builder\\Form\\ConfigureBlockFormBase->rebuildLayout(Object) (Line: 26)\nDrupal\\layout_builder\\Form\\ConfigureBlockFormBase->rebuildAndClose(Object) (Line: 242)\nDrupal\\layout_builder\\Form\\ConfigureBlockFormBase->successfulAjaxSubmit(Array, Object) (Line: 39)\nDrupal\\layout_builder\\Form\\ConfigureBlockFormBase->ajaxSubmit(Array, Object, Object)\ncall_user_func_array(Array, Array) (Line: 69)\nDrupal\\Core\\Form\\FormAjaxResponseBuilder->buildResponse(Object, Array, Object, Array) (Line: 109)\nDrupal\\Core\\Form\\EventSubscriber\\FormAjaxSubscriber->onException(Object, 'kernel.exception', Object)\ncall_user_func(Array, Object, 'kernel.exception', Object) (Line: 142)\nDrupal\\Component\\EventDispatcher\\ContainerAwarForeEventDispatcher->dispatch(Object, 'kernel.exception') (Line: 229)\nSymfony\\Component\\HttpKernel\\HttpKernel->handleThrowable(Object, Object, 1) (Line: 92)\nSymfony\\Component\\HttpKernel\\HttpKernel->handle(Object, 1, 1) (Line: 58)\nDrupal\\Core\\StackMiddleware\\Session->handle(Object, 1, 1) (Line: 48)\nDrupal\\Core\\StackMiddleware\\KernelPreHandle->handle(Object, 1, 1) (Line: 106)\nDrupal\\page_cache\\StackMiddleware\\PageCache->pass(Object, 1, 1) (Line: 85)\nDrupal\\page_cache\\StackMiddleware\\PageCache->handle(Object, 1, 1) (Line: 48)\nDrupal\\Core\\StackMiddleware\\ReverseProxyMiddleware->handle(Object, 1, 1) (Line: 51)\nDrupal\\Core\\StackMiddleware\\NegotiationMiddleware->handle(Object, 1, 1) (Line: 23)\nStack\\StackedHttpKernel->handle(Object, 1, 1) (Line: 718)\nDrupal\\Core\\DrupalKernel->handle(Object) (Line: 19)\n", name: "AjaxError", stack: "@http://XXXXX.docksal/core/misc/ajax.js?v=9.5.5:92:32\n@http://XXXXX.docksal/core/misc/ajax.js?v=9.5.5:642:3\n" }
ajax.js:92:32

Thank you.

1
  • wrap $params = Url::fromUri("internal:/" . $alias)->getRouteParameters(); in a try catch seems $alias may not be what you expect ?
    – taggartJ
    Apr 14 at 5:39

1 Answer 1

1

More general for the block, if you want to make sure the theme function is only used when viewing the node and not in other node routes like editing, then check the route name first:

function mytheme_preprocess_block(&$variables) {
  $route_match = \Drupal::routeMatch();
  $variables['#cache']['contexts'][] = 'route';
  if ($route_match->getRouteName() == 'entity.node.canonical') {
    $node = $route_match->getParameter('node');
    ...

More specific for the layout builder in node preprocess:

function mytheme_preprocess_node(&$variables) {
  $route_name = \Drupal::routeMatch()->getRouteName();
  $variables['#cache']['contexts'][] = 'route.name.is_layout_builder_ui';
  if ($route_name && !str_starts_with($route_name, 'layout_builder.')) {
    $node = $variables['node'];
    ...

I've also added the necessary cache data.

Your Answer

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

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