How to add a "?destination=URL" to the node links I am trying to override node links by using hook_node_view_alter(), so my code looks like:

$cancel_link = 'admin/some_path/'.$found_id.'cancel';

$build['links']['node']['#links']['cancel'] = array(
        'title' =&gt; t('Cancel'),
        'href' =&gt; $cancel_link,
        'html' =&gt; TRUE,
        'attributes' =&gt; array(
          'title' =&gt; 'Cancel',
        ),
      );


and it works fine. But I also need to add "?destination=URL" to links and unfortunately, trying several different approaches didn't work for me. In particular:

I copied the whole Good Example code from https://www.drupal.org/docs/7/theming/overriding-themable-output/how-to-add-a-destinationurl-to-the-request-new-password and replaced my code with:

$build['links']['node']['#links']['cancel'] = l(t('Request new password'), 'user/password', array('query' =&gt; array('destination' =&gt; 'homepage', 'foo' =&gt; 'bar'), 'attributes' =&gt; array('title' =&gt; t('Request new password via e-mail.'))));


but the link didn't show up at all.

Example on https://www.zyxware.com/articles/5195/how-to-set-destination-as-the-link-value-in-the-l-in-case-of-urls-with-parameters didn't work.

Tried to adapt the accepted answer on use URL with query as URL destination as:

  $query_string = array('destination' =&gt; 'service/922');
  $url = url($cancel_link, array('query' =&gt; $query_string));
  $build['links']['node']['#links']['cancel'] = array(
    'title' =&gt; t('Cancel'),
    'href' =&gt; $url,
    'html' =&gt; TRUE,
    'attributes' =&gt; array(
      'title' =&gt; 'Cancel',
    ),
  );


unfortunately, it is also giving %3Fdestination%3Dservice/922 in the browser address bar. What I am doing wrong here?

Addition: Using dpm() I've figured out the above examples all output ready to use links like &lt;a href="/user/password?destination=homepage&amp;amp;foo=bar" title="Request new password via e-mail."&gt;Request new password&lt;/a&gt;

However, if I dpm the link in my function it still gives raw array:

(Array, 4 elements)
title (String, 6 characters ) Cancel
href (String, 33 characters ) admin/some_path/id/cancel
html (Boolean) TRUE
attributes (Array, 1 element)
title (String, 6 characters ) Cancel


And I wonder is it possible to add destination at this stage at all or do I have to intercept the link at a later steps like for example while themeing?
You are doing it correctly but the theme_links() function is called after you create the link. That function calls the l() function, which in turn calls the url() function, which in turn calls drupal_encode_path(), and it's here your Url is getting encoded.

If you override the theme_links() function, you can undo the encoding. Copy the theme_links() function from theme.inc into the template.php of your theme. The function should be named mytheme_links() or, if you want it to apply only to nodes, you can name it mytheme_links__node(). The original theme_links() function has this:

if (isset($link['href'])) {
  // Pass in $link as $options, they share the same keys.
  $output .= l($link['title'], $link['href'], $link);
}


You can replace it with this to undo the encoding:

if (isset($link['href'])) {
  // Pass in $link as $options, they share the same keys.
  $link_html = l($link['title'], $link['href'], $link);
  // Decode the link HTML before adding it to the output
  $link_html = rawurldecode($link_html);
  $output .= $link_html;
}


This is just a basic explanation. There are good reasons for encoding links, so you might want to restrict the links you decode.