1
votes

I'm trying to show updated results for a CCK Computed Field.

The computation is based on fields in another node, so are not being automatically updated.

So: I'm calling node_save($node) in hook_view, which does make the adjustment but the results don't show until I refresh the page.

Is there a way to refresh the page automatically, or should I be approaching this from a different angle?

Edit: In response to Henrik's questions, here's more detail:
The hook_view and its node_save are below, the rest of the code is in a Computed Field in the 'project' content type, summing up values from another node. Without the node_save, I have to edit and save the 'project' node to get the result. With it, I just need to refresh the page.

Adding drupal_goto(drupal_get_destination()) in the hook_view gives a 'page not found', rather than the vicious loop I was expecting. Is there another place I could put it?

function mymodule_nodeapi(&$node, $op, $teaser = NULL, $page = NULL) {
  switch ($op) {
    case 'view':
      if($node->type == 'project') {
        project_view($node);
      break;
      }
  }
}

function project_view($node) {
    node_save($node);
    return $node;
}
2
Thanks for the clarification - I updated my answer with some new options, as well as fixing my bone headed first suggestion for the redirection ;) - Henrik Opel

2 Answers

2
votes

Edit 1: Given the newly posted code and additional explanations, I have three suggestions that might solve the problem without redirecting:

  1. As project_view() does not take the node argument by reference, you might want to actually grab its (potentially updated) result in mymodule_nodeapi by writing

    $node = project_view($node);
    

    instead of just

    project_view($node);
    
  2. If that works, it should also work without the indirection via project_view() by just calling node_save($node) directly in mymodule_nodeapi. (node_save() takes the node argument by reference).

  3. AFAIK, computed fields basically provide two working modes that you can switch via checkbox on the field configuration form:

    1. Computing the field once on node_save(), storing the result in the database, updating only on new save operations.
    2. Not storing the field at all, instead recomputing it every time the node is viewed.

    Have you tried the 'always recompute' option already?


Edit 2: My original answer was flawed in two ways at once, as it used a completely wrong function to retrieve the current request URI and did not check for recursion (as lazysoundsystem pointed out very courteously ;)

So the following has been updated to an actually tested version of doing the redirection:

Is there a way to refresh the page automatically

You could try:

if (!$_REQUEST['stop_redirect']) {
  drupal_goto(request_uri(), array('stop_redirect' => true));
}

This will cause Drupal to send a redirect header to the client, causing a new request of the current page, making sure not to redirect again immediately.

1
votes

If the value is only ever going to be computed, you could just add something to your node at load time.

function mymodule_nodeapi(&$node, $op, $teaser = NULL, $page = NULL) {
  switch ($op) {
    case 'load':
      if($node->type == 'project') {
         $node->content['myfield'] = array('#value' => mymodule_calculate_value(), '#weight' => 4, '#theme' => 'my_theme');  
       }
      break;
      }
  }
}