I am trying to use the computed field module to reveal data about nodes to the Views module. The problem is, the data I am trying to reveal is not created until after the node has been created.

Let me explain what I am trying to accomplish. I am using the E-Publish module to group together a CCK content type I created for magazine articles. For those not familar with E-Publish, it is like the book module, but it allows editions of a publication. I would like the views I create to be able to show the dateline and publication date of the particular edition to which an articles has been assigned.

The problem is, I have to create the article nodes first, then I can go into the E-Publish module and assign them to a particular edition. So when the node is saved for the first time, the computed field will be null because there is no edition associated with the node.

In the code box of the computed field, I am doing the following:

if (!$node->nid) {
  node_save($node);
}

$sql = "SELECT e.eid, e.pubdate, e.dateline FROM {epublish_edition_node} en INNER JOIN {epublish_edition} e ON e.eid = en.eid WHERE en.nid = %d";
$query = db_query($sql, $node->nid);
$result = db_fetch_object($query);

$node_field[0]['value'] = $result->dateline;
$node_field_listing_date[0]['value'] = strtotime($result->pubdate);

The computed field retrieves the dateline of the assigned edition ("September 2006"), but also sets field_listing_date[0]['value'] to the assigned edition's publication date ("MM/DD/YYYY"). The second field is common to all nodes on my site, and allows me so sort magazine and non-magazine content by date, since it is really difficult to sort on something like "July/August 2006".

So the problem is, I have found that the only way to get the computed field and field_listing_date to correctly update is to go to each node AFTER I have assigned it to an edition, click "edit", then "submit". The computed fields then update themslves. This seems very tedious considering that a typical magazine will have 30 or so nodes.

I have also tried not storing the computed field in the database, hoping that would mean that what's in the PHP code box will be executed every time the page is called, but that doesn't seem to work either. I did check to make sure that the caching features were off. Only going into edit mode and then saving the node seems to work.

So my questions are:

1. What events/actions cause the computed fields to update themselves?
2. Is there any way to do a batch recompute, where with a single click I can have all the nodes with computed fields recompute the values for those fields?
3. If I do not store the computed fields in the database, will I need to create placeholder fields for both the dateline and pubdate in order for them to appear in the Views module? (I suspect that the answer is yes.)

I get the alternative is to try and get the E-publish values to appear in Views, but I have no idea where to even start looking for that.

I would appreciate any help or ideas.

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

wrunt’s picture

I haven't got a good answer for how to do this. I think the best course would be to implement some views hooks for the epublish module.

In answer to your questions:
1. What events/actions cause the computed fields to update themselves?
A stored computed field is computed field is computed when the node is inserted or updated. A non-stored computed field is computed when the node is loaded.

2. Is there any way to do a batch recompute, where with a single click I can have all the nodes with computed fields recompute the values for those fields?
No easy way that I know of. You may be able to write a script that loads each node you want updated, then saves it (using node_load and node_save).

3. If I do not store the computed fields in the database, will I need to create placeholder fields for both the dateline and pubdate in order for them to appear in the Views module? (I suspect that the answer is yes.)
The answer is yes, sort of. Views loads things from the database itself, it doesn't call node_load. If the value isn't in the database then views won't see it. I'm not sure how you would create placeholder values that would solve this problem, since the placeholders need to be saved to the database at some point. Placeholders would need to be saved during node_save, such as when you edit and save a node.

In short it looks like your options are:
1. Write views hooks for the epublish module, or
2. Write a script which loads and saves the nodes you want updated.

jimyhuang’s picture

"A non-stored computed field is computed when the node is loaded."

I have a question about recompute, when the node is reload?

wrunt’s picture

Drupal loads a node using node_load any time that a module needs more than just the node id (nid) or title. node_load is defined in modules/node.module, and calls hook_load, and hook_nodeapi with the 'load' op. When a ckk node is being loaded, content_load gets called, and content_load calls field hooks with the 'load' op. That's the point at which a non-stored computed field is computed. At this same point a stored computed field would have been loaded from the database, rather than being computed.

Does that answer your question?

jimyhuang’s picture

Category: support » task
Status: Active » Needs review
FileSize
2.12 KB

wrunt,
thanks for your reply.

I made a function that can set every computed field how long to recompute by cron.

It's useful for sometime I don't a static data save in the database, but not change every time.

jimyhuang’s picture

FileSize
2.09 KB

delete unused dpr().

dmjossel’s picture

Computed values that are not stored in the database do not expose themselves to Views, so there is probably a need for a way to recalculate stored computed values (or selected ones) via cron as well.

ardee-1’s picture

Yes, desperately! Ideal would be a cron-based (and manually-runnable) way to update computed values that ARE stored in the database. [Hopefully the associated node(s) would NOT be marked as updated by this action.]

If this existed, Computed Field would become VERY powerful indeed, adding an unprecedented level of control to a Drupal user who cannot or chooses not to edit PHP files directly. (Personally, I want all my changes to the site, except perhaps those in .CSS files, to be "managed" -- kept in the database.)

ray007’s picture

I think the other options (which I was thinking about initially) is to compute the value at display-time, not at node-edit-time.
That way it's always current ...

Or is there another way to generate a value at node-display-time?

PS: I'm using computed_field on drupal 5

charlesc’s picture

Hi all,
How could we setup a script to recompute the value and save it into the database?

ncameron’s picture

Hey there,

I faced the same problem and used the following script to load and save all nodes of a certain type (in this case CCK profiles).

<?php
// This query is used to load all the nids of a specific content type into an array. Change `node_content_profile' to the name of the content type.
$query = 'SELECT nid
FROM `node_content_profile';

// Create an array to store the query info
$profilenidarray = array();
 
 //exectue the query using db abstraction stuff
$profilenidarray = db_query($query);

// For each nid this will load and then save the node
while ($nodeID = db_fetch_array($profilenidarray)){

//This time limit is important, if it is removed the query will exceed the 30sec limit.
set_time_limit(5);

$PNID = node_load($nodeID["nid"]);
node_save($PNID);

}
// Just so you know its done!
print 'done';
?>

The code can be executed from the devel box at the bottom or just paste it in a page and enable php code.

Hope this helps some ppl out.

Cheers,

Neil

mwander’s picture

Neil,

Your code worked well for me in 5.x - great job!

I think there was an extra ` in this line (corrected below):
$query = 'SELECT nid
FROM node_content_profile';

Thank you.

Moonshine’s picture

Status: Needs review » Closed (fixed)

Closing out old Drupal 4.7 issues, as it is no longer a supported release.