I was looking at how hook_link is implemented and found something in function node_link() that, at a first sight, looks a bit strange. I'm wondering if this is something left to fix when obj2array/array2obj were removed.

This is node_link() in node.module:

function node_link($type, $node = 0, $main = 0) {
  $links = array();

  if ($type == 'node') {
    if (array_key_exists('links', $node)) {
      $links = $node->links;
    }

    if ($main == 1 && $node->teaser && $node->readmore) {
      $links[] = l(t('read more'), "node/$node->nid", array('title' => t('Read the rest of this posting.'), 'class' => 'read-more'));
    }
  }

  return $links;
}

1) I believe the use of array_key_exists() is wrong here. $node is an object.
2) Is $links = $node->links; really needed?

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

scroogie’s picture

On http://php.net/array_key_exists its explicitly stated that array_key_exists() works on objects, too. $links = $node->links is because you have to return the value, otherwise you would have to introduce another if statement at the return clause, which is possibly slower than having a temporary variable.

markus_petrux’s picture

On http://php.net/array_key_exists its explicitly stated that array_key_exists() works on objects, too.

Oops. I missed that comment, thanks

$links = $node->links is because you have to return the value, otherwise you would have to introduce another if statement at the return clause, which is possibly slower than having a temporary variable.

hmm... $links is initialized at the top of node_link(). It does not need to be initialized again. Anything returned by hook_link is appended (or array_merged) to $node->links.

This is node_view():

  if ($links) {
    $node->links = module_invoke_all('link', 'node', $node, !$page);
  }

This is module_invoke_all():

function module_invoke_all() {
  $args = func_get_args();
  $hook = array_shift($args);
  $return = array();
  foreach (module_implements($hook) as $module) {
    $function = $module .'_'. $hook;
    $result = call_user_func_array($function, $args);
    if (isset($result) && is_array($result)) {
      $return = array_merge($return, $result);
    }
    else if (isset($result)) {
      $return[] = $result;
    }
  }

  return $return;
}

Other hook_link implementation I've seen just do:

function example_link($type, $node = 0, $main = 0) {
  $links = array();
  if (whatever) {
    $links[] = l('foo', 'bar');
  }
  return $links;
}

I don't get why node_link is different. Sorry, maybe it is in front of me, but I can't see it. I wouldn't have post about it, but it seems to me that even if the expression where array_key_exists() is used in node_link is TRUE (see below), $node->links is still empty. Hence, this code is not needed. Well, that's what it seems to me.

    if (array_key_exists('links', $node)) {
      $links = $node->links;
    }

Is it possible that $node->links contains something else before that point? Maybe filled at node load time by another module? If so, if that is correct, then it looks like other hook_link implementations should also behave as node_link does?

scroogie’s picture

I just looked at the code from the syntactical point of view at first. Now I think your second point is right, this seems to be redundant.

markus_petrux’s picture

Title: array_key_exists in node_link() ? » Remove redundant code from node_link()
Status: Active » Needs review
FileSize
459 bytes

Thanks for checking :-)

Here's a patch that removes that piece of code from node_link().

Robrecht Jacques’s picture

Priority: Normal » Minor
Status: Needs review » Reviewed & tested by the community
FileSize
664 bytes

It is indeed unclear why that piece of code is needed. In node_view() $node->links is set by calling all hook_link(), including the node_link(), and then array_merged. So this is basically a no-op.

Rerolled patch.
Ready to commit.

killes@www.drop.org’s picture

committe Marcus' patch to 4.7

drumm’s picture

Status: Reviewed & tested by the community » Fixed

Committed to HEAD.

Anonymous’s picture

Status: Fixed » Closed (fixed)