Score:-2

Editing the "Send private message" link to include the username

in flag
j0e

I'm using the Private Message module version 8.x-2.0-beta16 and I want to change the message from 'Send private message' to 'Send private message to @username' which should display the username from the user's page that we are visiting and contacting.

The module uses the following code.

'#title' => t('Send private message'),

Is there are way to override this line directly and insert the username? I tried without success.

The relevant code is located in: private_message\src\Service\PrivateMessageService.php#L336-382.

public function createRenderablePrivateMessageThreadLink(array &$build, EntityInterface $entity, EntityViewDisplayInterface $display, $view_mode) {
  if ($display->getComponent('private_message_link')) {
    if ($entity instanceof UserInterface) {
      $author = $entity;
    }
    else {
      $author = $entity->getOwner();
    }
    $current_user = \Drupal::currentUser();
    if ($current_user->isAuthenticated()) {
      if ($current_user->hasPermission('use private messaging system') && $current_user->id() != $author->id()) {
        $members = [$current_user, $author];
        $thread_id = $this->mapper->getThreadIdForMembers($members);
        if ($thread_id) {
          $url = Url::fromRoute('entity.private_message_thread.canonical', ['private_message_thread' => $thread_id], ['attributes' => ['class' => ['private_message_link']]]);
          $build['private_message_link'] = [
            '#type' => 'link',
            '#url' => $url,
            '#title' => t('Send private message'),
            '#prefix' => '<div class="private_message_link_wrapper">',
            '#suffix' => '</div>',
          ];
        }
        else {
          $url = Url::fromRoute('private_message.private_message_create', [], ['query' => ['recipient' => $author->id()]]);
          $build['private_message_link'] = [
            '#type' => 'link',
            '#url' => $url,
            '#title' => t('Send private message'),
            '#prefix' => '<div class="private_message_link_wrapper">',
            '#suffix' => '</div>',
          ];
        }
      }
    }
    else {
      $url = Url::fromRoute('user.login');
      $build['private_message_link'] = [
        '#type' => 'link',
        '#url' => $url,
        '#title' => t('Send private message'),
        '#prefix' => '<div class="private_message_link_wrapper">',
        '#suffix' => '</div>',
      ];
    }
  }   
}
sonfd avatar
in flag
Don’t hack a module. Create a patch with your change and apply it with composer.
j0e avatar
in flag
j0e
I don't mind patching instead of hacking. But the question remains...
leymannx avatar
ne flag
Can't you maybe preprocess the link and then check for `$variables['element']['#prefix'] === '<div class="private_message_link_wrapper">'` and then simply replace the `$variables['element']['#title']`?
sonfd avatar
in flag
Yes, or you could even override the service and extend this method. See [How to override a service](https://drupal.stackexchange.com/questions/292562/how-to-override-a-service).
Score:2
in flag

I think you're asking, "How can I create a translated string 'Send a private message to @username' where @username is replaced with the name of the user currently being viewed?"

If you're viewing the user's page, you can do this like:

// Get the user object currently being viewed from the route parameters.
$user = \Drupal::routeMatch()->getParameter('user');
// If we have a valid user object.
if ($user instanceof Drupal\user\Entity\User) {
  $message = t('Send a private message to @username', [
    '@username' => $user->getDisplayName(),
  ]);
}

However, looking at the specific code you posted, you're not guaranteed to be on the user's page. Additionally, the user that is to receive the message is already determined and stored in $author:

// I.e. user's page.
if ($entity instanceof UserInterface) {
  $author = $entity;
}
// I.e. a node or other entity authored by a user.
else {
  $author = $entity->getOwner();
}

In this case, you could just use something like:

$message = t('Send a private message to @username', [
  '@username' => $author->getDisplayName(),
]);
leymannx avatar
ne flag
Still the question how they get it to override the current message. Maybe they should open a feature request and provide a patch/MR with the code you suggested.
sonfd avatar
in flag
Agreed, definitely don't hack the module. As we mentioned above, I think the options are 1. Create an issue / post a patch to d.o and apply with composer. 2. Preprocess the link and do logic there. 3. Override the service and extend its class to override just this one method to alter the link text.
leymannx avatar
ne flag
Oh yeah, overriding the service, even better.
j0e avatar
in flag
j0e
Thanks @sonfd. I didn't notice the $author variable. I got this to work based on your third solution, replacing the #title line with: `'#title' => t('Send private message to @username', ['@username' => $author->getDisplayName()]),`
sonfd avatar
in flag
@j0e - Great! I definitely recommend at least making a patch for your change and having composer apply it. Composer will attempt to reapply the patch when you update the module so your change is preserved (if the patch can't be applied then composer will tell you it failed so you can go fix it). As leymannx said above, you could also post as a FR on drupal.org (I would), but that's up to you :)
mangohost

Post an answer

Most people don’t grasp that asking a lot of questions unlocks learning and improves interpersonal bonding. In Alison’s studies, for example, though people could accurately recall how many questions had been asked in their conversations, they didn’t intuit the link between questions and liking. Across four studies, in which participants were engaged in conversations themselves or read transcripts of others’ conversations, people tended not to realize that question asking would influence—or had influenced—the level of amity between the conversationalists.