Hi,

I've been testing Computed fields with the multigroup module and it caused a problem because how the way Computed Fields implements hook_content_is_empty(). It always returns FALSE, and that within the context of a multigroup is problematic. Please, see the following comments for details:

http://drupal.org/node/119102#comment-1164604

In my working copy of Computed Fields I tried the following code that seems to work nicely:

/**
 * Implementation of cck hook_content_is_empty().
 */
function computed_field_content_is_empty($item, $field) {
  if ($field['data_type'] == 'int' || $field['data_type'] == 'float') {
    return !is_numeric($item['value']);
  }
  return empty($item['value']);
}
Support from Acquia helps fund testing for Drupal Acquia logo

Comments

markus_petrux’s picture

Status: Active » Needs review
BWPanda’s picture

I setup a new Drupal installation to test Computed Field with Multigroup (need it for a site I'm working on). I installed the cck and computed_fields modules, patched both, then tried adding a computed field to a multigroup, only to see this familiar error message:
This change is not allowed. The field Total handles multiple values differently than the Content module. Making this change could result in the loss of data.

As I was trying this, I realised that you set the version as 1.0-beta2 (I had downloaded the latest .dev). So I disabled the computed_field module, uninstalled it, deleted the folder from the server, then installed the beat2 version and patched it - same error.

I'd mark this as 'Patch (code needs work)', but I'm not convinced I'm not doing something wrong...
Any ideas?

markus_petrux’s picture

BWPanda #2: You're right. There's something else that needs to be added to computed fields module in order to support content multigroup. The reason is that widgets that are coded to support their own multiple values need to implement a couple of multigroup exposed hooks.

Please, try adding the following to the end of computed_fields.module

/**
 * Implementation of hook_content_multigroup_allowed_widgets().
 */
function computed_field_content_multigroup_allowed_widgets() {
  return array('computed');
}

/**
 * Implementation of hook_content_multigroup_no_remove_widgets().
 */
function computed_field_content_multigroup_no_remove_widgets() {
  return array('computed');
}

In summary: there are 2 different issues here.

1) Function computed_field_content_is_empty() needs to fixed to return conditional result.
2) Computed fields module needs to implement a couple of content multigroup hooks.

markus_petrux’s picture

I'm attaching to patches.

1) computed_field-is_empty-349548-4.patch: modifies hook_content_is_empty() implementation to return conditional result.

2) computed_field-multigroup-349548-4.patch: Implements hook_content_multigroup_allowed_widgets() and hook_content_multigroup_no_remove_widgets() to add support for the multigroup module. This is necessary to tell the multigroup module that widgets that deal with multiple values themselves are compatible with the multigroup module, which is true for this module.

The second patch works with the latest version of multigroup module posted here #119102: Combo field - group different fields into one ...but it could be changed. I would not commit this to CVS until the multigroup module is commited to CCK repository.

BWPanda’s picture

Ok, that at least lets me add the computed field to the multigroup.

However, I've noticed that if the computed field is set to 'required', when creating a node it gives the error: [computed field] field is required in group [multigroup]...

markus_petrux’s picture

It seems computed_field_content_is_empty() is returning TRUE in your case for some reason. That may depend on the data type of the computed field and the code used to compute the value.

BWPanda’s picture

Computed Code: $node_field[0]['value'] = $node->field_value1[0]['value'] + $node->field_value2[0]['value'];
Data Type: Was the default 'varchar', but I changed it to 'float', then to 'int', all with the same error...

BWPanda’s picture

I also just tried: $node_field[0]['value'] = $node->value1[0]['value'] + $node->value2[0]['value'];
Same result.

markus_petrux’s picture

If you expect to hold a number, you may wish to set the computed field type to int or float.

Then try something like the following to compute the value of the field:

if (isset($node->field_value1[0]['value']) || isset($node->field_value2[0]['value'])) {
  $node_field[0]['value'] = $node->field_value1[0]['value'] + $node->field_value2[0]['value'];
}
else {
  $node_field[0]['value'] = NULL;
}

When the source fields are not set, then the computed field value would be set to NULL, and that will result in computed_field_content_is_empty() to work as expected.

markus_petrux’s picture

In fact, we would have to compute the values for all the items in the subgroup, so we would need something like the following instead:

foreach (array_keys($node->field_value1) as $delta) {
  if (isset($node->field_value1[$delta]['value']) || isset($node->field_value2[$delta]['value'])) {
    $node_field[$delta]['value'] = $node->field_value1[$delta]['value'] + $node->field_value2[$delta]['value'];
  }
  else {
    $node_field[$delta]['value'] = NULL;
  }
}

There's an additional problem, and it is that the computed field code is not executed when the node edit form is being validated. I beleive there's something else that needs to be done here in order to have the correct values when the multigroup checks if the fields are empty or not. I'll try to investigate this further. Meanwhile, try unsetting the required flag of the computed field.

markus_petrux’s picture

Correction to patch for content_is_empty() in #4 above. Function arguments are missing. My bad. The code I posted when opening the issue was correct, but the patch in #4 was not. This should be fixed in the patch attached here. The other patch, the one that implements the multigroup hooks in #4 is also necessary.

@BWPanda: aside from the patches here, I have not been able to solve the error "[computed field] field is required in group [multigroup]" when the computed field is required. I believe this is because there is no real widget and the check for required fields has this dependence here. Anyway, computed fields should work with the patches here. Just do not set them as required. The other fields in the multigroup can, though.

The method to compute values for all items in the multigroup should use a foreach loop similar to the one I posted in #10 above. Note the code to compute a particular field is invokes just once for all items in a group. So the code should process all items.

BWPanda’s picture

I don't know why a hidden/computed field would have a 'required' option... How would it not be set anyway?
Thanks Markus, I'll just not set 'required'. Will test more when I get home after work.

BWPanda’s picture

That all seems to work fine, though I didn't seem to have to surround the 'Display Format' in a foreach loop...

Just wondering if it's possible (and practical) to put the foreach loop in the module code, rather than making users do it. Something like this:?

function _computed_field_compute_value(&$node, $field, &$node_field) {
  foreach (array_keys($node->field_value1) as $delta) {

    if (isset($field['code'])) {
      eval($field['code']);
    }

  }
}

I didn't make it into a patch as I have no idea whether it'd work or not, and it's a bit hard to see what's happening when you can't see the field in question :)

BWPanda’s picture

Having said that, there is an issue when only creating 1 instance of the multigroup (i.e. fill in the multigroup but don't click 'add more values').
Nothing shows up...

Moonshine’s picture

Status: Needs review » Postponed

Sorry to get back to this so late, but it looks like multigroup is stalled ATM. So I'll mark this as postponed for now, at least until the deletion issue is resolved:

#196421: Deleting unwanted multiple values / multiple values delta issues

and the multigroup discussion resumes:

#119102: Combo field - group different fields into one

ballerjones’s picture

I've tried adding both patches to beta2 but the computed field inside the multivalue is always 0. What am I missing?

this is the code for my computed field:

$node_field[0]['value'] =
$node->multigroupfield[0]['value'] +
$node->multigroupfield2[0]['value'];

markus_petrux’s picture

@Moonshine #15: Hi, I'm setting this back to active. The multigroup can be found on the CCK repository, branch 6.x-3.x. :)

As per the patches that may allow to use Computed fields with multigroups, I would say these are:

markus_petrux’s picture

Status: Postponed » Active

@ballerjones: With multiple value fields, you should perform a loop, something like in comment #10 above, or something like the example posted in your rules related issue:

#495610: printing multigroup fields

ballerjones’s picture

I have patched as you suggested successfully. However, I got the following error.

After adding a computed field to a multigroup: (content type screen)

user warning: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ') SELECT vid, nid, 0, FROM content_type_mgtest' at line 1 query: INSERT INTO content_field_computedfieldtest (vid, nid, delta, ) SELECT vid, nid, 0, FROM content_type_mgtest in /srv/www/internal/modules/cck/includes/content.admin.inc on line 1523.

This was how I added your loop code from #10:

$node_field[0]['value'] = "<?php
foreach (array_keys($node->field_value1) as $delta) {
  if (isset($node->field_value1[$delta]['value']) || isset($node->field_value2[$delta]['value'])) {
    $node_field[$delta]['value'] = $node->field_value1[$delta]['value'] + $node->field_value2[$delta]['value'];
  }
  else {
    $node_field[$delta]['value'] = NULL;
  }
}
?>";

Upon testing node submission, the computed field's title is shown, but there is no value. FYI, this was tested on a blank content type, with 1 multigroup (named mgtest) and two textfield-integer fields (value1 and value2) and the computed field.

Perhaps someone could post the export code for a content type with a working computed field + multigroup combination?

ballerjones’s picture

Can anyone shed some light on this issue?

mcload’s picture

Subscribing. Computed Field is very important for advanced use of multigroups.

mcload’s picture

&ballerjones

Maybe you should remove the first and last lines in your code at #19

mcload’s picture

I tested the patch at #17. It works for me. Thank you markus_petrux.

break9’s picture

I have tried the patch at # 17 but i still get this error on page load:

: array_keys() []: The first argument should be an array in on line

and i get this error when i try to "add more values" to the multigroup in node edit:

Warningfunction.array-keys/home2/break9/public_html/sites/all/modules/cck/modules/content_multigroup/content_multigroup.node_form.inc143

using: cck3 multigroups and computed field

bsnodgrass’s picture

subscribing

BenK’s picture

Subscribing and testing...

csc4’s picture

Tested the patches at #17 and working excellently. Thanks @markus_petrux

tomsm’s picture

subscribing...
I hope that these patches will be added to the dev version soon.

carligraph’s picture

Version: 6.x-1.0-beta2 » 6.x-1.0-beta3

if patched with #17 it works now, without any warning, if adding the computed field to the multigroup.
the following is my computed code:

foreach (array_keys($node->field_category) as $delta) {
$result1 = db_result(db_query("SELECT field_default1_value FROM content_type_categories WHERE nid=%d",$node->field_category[$delta][nid]));
$result2 = db_result(db_query("SELECT field_default2_value FROM content_type_categories WHERE nid=%d",$node->field_category[$delta][nid]));
if (!isset($node->field_value1[$delta]['value'])) {
$node_field_value1[$delta]['value']=$result1;
} elseif (!isset($node->field_value2[$delta]['value'])) {
$node_field_value2[$delta]['value']=$result2;
}
}

anyhow, it makes no sense to put this code into the multigroup - or does it ?
also, it doesnt fill any field, but thats maybe another issue..

->edit: ok, it works now, should have been $node->field_value1[.. instead of $node_field_value1[..

(field_category is a nodereference)

solidarity’s picture

I just applied both patches from #17. I have two decimal fields and a computed field in each multigroup. The computed field is setup to simply multiply the two other fields. The computed field shows up in the first instance of the multigroup, but if I add another, the computed field is a no show.

So it works ... kinda. Any help appreciated!

BWPanda’s picture

Version: 6.x-1.0-beta3 » 6.x-1.x-dev
Status: Active » Needs review
FileSize
976 bytes

Works for me.

I've combined both patches from #17 into one, applied against the latest dev release.
Be great to get this tested and committed.

mikeytown2’s picture

Status: Needs review » Reviewed & tested by the community

#31 works for me. Should probably add a note to the help text about doing foreach (array_keys($node->field_existing_field_in_multigroup) as $delta)

alexharries’s picture

Patch #17 worked superbly for me too. Thank you :)

andyboutte’s picture

subscribe

Anonymous’s picture

@solidarity I'm running into the same issue: the computed field is working only for the first instance in the group, and not in the second set, third, etc. Did you ever find a solution?

8bitwright’s picture

@solidarity @Jyorraku same issue here? did you find a solution?

Anonymous’s picture

@botty1, I didn't find a solution. Although if you switch the sequence of the group, I find that the computed field in whichever is the first group works.

hey_germano’s picture

@solidarity @Jyorraku @botty1 - I'm running into the same thing. My 3 computed fields live outside of my multi-groups, but only the first one will save any data. Has anybody found a way to fix this? I'm using the latest dev version of computed field and the patch in #31.

Moonshine’s picture

Status: Reviewed & tested by the community » Closed (fixed)

I've committed the patches from markus_petrux's #17 along with a few other items today. I'm sure someone will write in about their computed field string value of "0" not being empty. :) Thanks!

If nothing major pops up on the dev version of computed field in the next week then I'll do one last beta and get a final "out" before D7 hits. :/ Yeah sorry, too much going on. There is a D7 branch for Computed Field now though which should have a tarball on the project page soon.

svtlightning’s picture

Does anyone know of a way to use compute to sum (total) a column of the multigroup. I've got a sum of the row inside the multigroup but want to put a sum of a column outside the multigroup.

loopduplicate’s picture

Here is a working code example that contains computed fields in
unlimited type multigroups and a computed field outside of the
multigroup. It is for a work order system. The user enters
in hours and hourly rate for labor and they enter qty and unit price
for parts. The materials and labor costs all get totalled up:

I have a content type called Work Order that contains two
unlimited value multigroups, Labor and Parts.
The Labor multigroup contains four
fields:

  • Hours - Decimal - field_hours_work_order
  • Description - Text
  • Per Hour - Decimal - field_per_hour_work_order
  • Total - Computed - field_total_labor_work_order
    • Computed Code that multiplies hours and hourly rate
      • foreach (array_keys($node->field_hours_work_order) as $delta) {
          if (isset($node->field_hours_work_order[$delta]['value']) && isset($node->field_per_hour_work_order[$delta]['value'])) {
            $node_field[$delta]['value'] = $node->field_hours_work_order[$delta]['value'] * $node->field_per_hour_work_order[$delta]['value'];
          }
        };
    • Data Type
      • Decimal
    • Not Null

The Parts multigroup also contains four fields:

  • Qty - Decimal - field_quantity_parts_work_order
  • Description - Text
  • Unit Price - Decimal - field_unit_price_work_order
  • Total - Computed - field_total_parts_work_order
    • Computed Code that multiplies Qty and Price
      • foreach (array_keys($node->field_quantity_parts_work_order) as $delta) {
          if (isset($node->field_quantity_parts_work_order[$delta]['value']) && isset($node->field_unit_price_work_order[$delta]['value'])) {
            $node_field[$delta]['value'] = $node->field_quantity_parts_work_order[$delta]['value'] * $node->field_unit_price_work_order[$delta]['value'];
          }
        };
    • Data Type
      • Decimal
    • Not Null

Next, I have a field called Total
that adds up all the Labor and Parts totals:

  • Computed Code that adds up all Labor and Parts totals for a grand total
    • $laborpartstotal = 0;
      foreach (array_keys($node->field_total_labor_work_order) as $delta) {
        if (isset($node->field_total_labor_work_order[$delta]['value'])) {
          global $laborpartstotal;
          $laborpartstotal += $node->field_total_labor_work_order[$delta]['value'];
        }
      };
      
      foreach (array_keys($node->field_total_parts_work_order) as $delta) {
        if (isset($node->field_total_parts_work_order[$delta]['value'])) {
          global $laborpartstotal;
          $laborpartstotal += $node->field_total_parts_work_order[$delta]['value'];
        }
      };
      
      $node_field[0]['value'] = $laborpartstotal;
      
  • Data Type
    • Decimal
  • Not Null

As a final step, I load up the Manage Fields page of my Work Order in a
browser with javascript turned off so I can make sure the field weights
are ok as they determine the order which the calculations take
place. I use a Firefox plugin called QuickJava to switch
javascript off. Then I make sure that the computed fields have
higher number weights than the fields they reference or the
calculations will require multiple node saves to calculate everything
(Which is unacceptable for accounting stuff.)

I'm not the best PHP programmer so this took me awhile to figure
out. Hope it helps someone. Let me know if I need to
clarify anything by sending me a PM here on drupal.org.

Peace.

Edit: I added this to the Computed Fields code snippets: http://drupal.org/node/1106840

tomsm’s picture

I have a multigroup with an unlimited number of items.

When I add more than 10 items I the following error:
number_format() expects parameter 1 to be double, string given in /home/fysiomed/domains/fysiomed.com/public_html/sites/all/modules/computed_field/computed_field.module(362) : eval()'d code on line 1.

When I add 10 or less items, everything is fine.

I have checked the delta values, these look ok:
0,1,2,3,...,10,11, etc.

I think that the computed field has a problem with delta 10 and higher.

Any ideas how to solve this?