1

I wrote my own implementation of OutboundPathProcessorInterface to rewrite the URL of nodes to use the content of their field_project_url field.

namespace Drupal\mymodule\PathProcessor;

use Drupal\Core\Render\BubbleableMetadata;
use Drupal\Core\PathProcessor;
use Drupal\Core\PathProcessor\InboundPathProcessorInterface;
use Drupal\Core\PathProcessor\OutboundPathProcessorInterface;
use Drupal\node\Entity\Node;
use Symfony\Component\HttpFoundation\Request;

class MymoduleFieldRedirectPathProcessor implements OutboundPathProcessorInterface {

  public function processOutbound($path, &$options = array(), Request $request = NULL, BubbleableMetadata $bubbleable_metadata = NULL) {

    if (isset($options['entity']) && is_object($options['entity']) && method_exists($options['entity'], 'hasField')) {
      $node = $options['entity'];

      if ($node->hasField('field_project_url') && !$node->field_project_url->isEmpty()) {
        $project_url = $node->field_project_url->getValue();

        if (preg_match("/^\/node\/[0-9]+\/(edit|translate|delete|translations)$/i", $path)) {
          // dont alter operational paths
        }
        else {
          $path = $project_url[0]['uri'];

          dpm($project_url[0]['uri']); // 'http://url.com'

          $options['absolute'] = TRUE;
          $options['external'] = TRUE;
          $options['base_url'] = null;
          $options['prefix'] = null;
        }

        if ($bubbleable_metadata) {
          $bubbleable_metadata->addCacheableDependency($node);
        }
      }
    }
    return $path;
  }

}

The teaser of that view has a title, an image linked to the content, and smart trimmed version of the body field, also linking to the content.

The value is appended, giving (for example) http://localhost:8888/myprojecthttp%3A//url.com.

This used to work, but I can't even get this right with older Drupal 8 versions.

What am I doing wrong?

6
  • 1
    I am not sure setting $options['external'] would work. processOutbound() should not be expected to redirect to external sites.
    – apaderno
    Apr 27, 2017 at 18:15
  • thats the clue i got from the drupal forums in the first place. this used to work though. is there any better way except for redirects?
    – Alex
    Apr 28, 2017 at 7:18
  • 1
    Just to understand, what are users allowed to enter in that field? What is its purpose? If the purpose is allowing users to create a repository of links, I would rather create a field that is shown as a clickable URL.
    – apaderno
    Apr 28, 2017 at 7:22
  • that field is a link field, so users can enter a url. when set, the node's url should be that url. i dont like redirects because actually its another unnecessary server request so setting the node actual url to that field url seemed legit
    – Alex
    Apr 28, 2017 at 7:25
  • Supposing it would work as you expect, it would a kind of redirect, without using HTTP headers. I don't see much difference. Also, the problem with that is that nodes would not be going to be easily editable, since normally first a user visits node/1 and then clicks on the Edit tab there. If you implement it as you describe, users should enter the path to edit a node directly on the browser URL bar.
    – apaderno
    Apr 28, 2017 at 7:57

1 Answer 1

0

That's the right code of the processOutbound method

  public function processOutbound($path, &$options = array(), Request $request = NULL, BubbleableMetadata $bubbleable_metadata = NULL) {

if (isset($options['entity']) && is_object($options['entity']) && method_exists($options['entity'], 'hasField')) {
  $node = $options['entity'];

  if ($node->hasField('field_project_url') && !$node->field_project_url->isEmpty()) {
    $project_url = $node->field_project_url->getValue();

    if (preg_match("/^\/node\/[0-9]+\/(edit|translate|delete|translations)$/i", $path)) {
      // dont alter operational paths
    }
    else {
      $path = ''; //Don't use $path variable at all

      dpm($project_url[0]['uri']); // 'http://url.com'
      $options['base_url'] = $project_url[0]['uri']; //Add your url as base_url

    }

    if ($bubbleable_metadata) {
      $bubbleable_metadata->addCacheableDependency($node);
    }
  }
}
return $path;

}

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.