I get 4 messages at each node page view (see below).
This is what I did:
- add settings to Nodereference field of content type A, referring content type B; save.
- edit/save settings of content type B.

Then I showed a node of type B, and got the following messages:
(I did not do 'Rebuild permissions' yet)
I do not get the warnings on other content types.

Notice: Undefined index: referenced in nodeaccess_nodereference_node_access_records() (line 489 of nodeaccess_nodereference.module).
Warning: array_keys() [function.array-keys]: The first argument should be an array in nodeaccess_nodereference_node_access_records() (line 489 of nodeaccess_nodereference.module).
Warning: Invalid argument supplied for foreach() in nodeaccess_nodereference_node_access_records() (line 489 of nodeaccess_nodereference.module).

Comments

johnv’s picture

Status: Active » Needs review
StatusFileSize
new2.78 KB

Please check attached patch. It contains the following:

@@ -465,7 +465,7 @@ function nodeaccess_nodereference_node_access_records($node)
- returns always an array, which gives easier logic, and is in accordance with hook documentation;
- has a small improvement, due to NANR_field_settings() now returning only array's.

@@ -564,15 +561,20 @@ function nodeaccess_nodereference_field_settings()
- logic is now clearer IMO;
- returns always an array, which is easier for parsing the resulting data, as in .._access-records() ;
- has some hints for #1630658: Less memory-usage in nodeaccess_nodereference_field_settings()

@@ -603,7 +608,7 @@ function nodeaccess_nodereference_check_cross_access()
- has a small modification to remove the message. Please check if the logic is not broken.

johnv’s picture

a better patch.

danielb’s picture

Any reason to remove if (!empty($field_data)) { ? Seems like a quick way to avoid the loop if the data isn't there? Especially if you propose we don't store anything at all for content types without the settings enabled?

Will have to make sure there is nowhere else that !empty() should be used as a result of your proposal.

danielb’s picture

I also think the TODO you have there should be handled by code that calls this function (by calling it an additional time to check the data first), probably not within the function.

danielb’s picture

For comparing old settings, can we get away with comparing arrays like (serialize($array1) == serialize($array2)) ?
I really don't want to hardcode all the things it should look for, or recurse through the array.

johnv’s picture

@#3, indeed, we do not need if (!empty($field_data)) { if the function ALWAYS returns an array, perhaps an empty one. I did not have the overview to remove it on other places.

@#4, I thought that this get/set function was a nice place to centralize the data. If done outside, you must make sure it is called on all set-statements.
@#5, I tried something like

$default_data = ... ;
$user_data = ... ;
$user_data = $default_data + $user_data ; // perhaps the $user_data contains extra unforeseen data, 
if ($user_data == $default_data) {...}

But I couldn't easily get a nice set of default_data in the fist place..

In some other module, we had $default_settings (but it was a simple array - this is more complex). You can mimic the submit data, and you can use it to set the field_settings, too

danielb’s picture

I might create a function that reduces the settings arrays to their bare minimums, will be necessary for the other issue too.

danielb’s picture

There's only one place that call this function to set it, I think I will do the reductions and tests there.

danielb’s picture

Title: 4 Messages on 'node view' page. » Cumulative settings improvements and fixes.
StatusFileSize
new5.58 KB

I got started and all of this is kinda related so it all blended together in my hand.
I'm marking the following as duplicates since there is a bit of crossover.
#1630658: Less memory-usage in nodeaccess_nodereference_field_settings()
#1630684: node_access_needs_rebuild(TRUE) is set too often.

I've attached a patch which hopes to address these issues. I've tested the new functions, but not quite sure how the whole thing comes together.

danielb’s picture

I'm not quite happy with it yet, I think there are some typical cases where it won't reduce the way it should because of the tree structure of the array. But it will reduce nicely when the settings aren't used at all.

danielb’s picture

Well I solved that somewhat by adding

<?php
  // Remove major areas of the variable if they are empty in the test array.
  foreach ($variable as $key => $value) {
    if (is_array($value) && empty($test[$key])) {
      unset($variable[$key]);
    }
  }
?>

before return $variable in nodeaccess_nodereference_reduce_variable().
However this loses the 'published' setting if it was changed - despite the related settings not being in use. Maybe it's not a good idea.

The other issue is that technically the keys 'author_published', 'author', 'all_published', and 'all' don't get used when the 'referenced' grants aren't set.

But again, do we really want to reset those, as they will be lost in the settings form too?

danielb’s picture

Actually...
the settings form could be changed to rely on the settings as they are stored in $instance, which don't get reset.

danielb’s picture

The updates also allow simplification of nodeaccess_nodereference_field_delete_instance()

danielb’s picture

new patch

danielb’s picture

If this works out a similar issue should be created for http://drupal.org/project/nodeaccess_userreference

danielb’s picture

this bit can probably be deleted, it's redundant with what happens later anyway

+  // If the test array is empty, then the variable can be considered empty.
+  if (empty($test)) {
+    return FALSE;
+  }
johnv’s picture

Nice, such a feuilleton.. :-)
I won't be able to test until next tuesday, so I'll await more episodes...

danielb’s picture

I will commit it, "Move fast and break things" right? works for facebook...
also brings in more testers, whether they know it or not

johnv’s picture

Status: Fixed » Needs review
StatusFileSize
new1.07 KB

I think this works fine. Thanks.

Addition 1: I couldn't resist creating an update function. It removes superfluous data in your variable.
The data will be deleted when you save a Node type, but who knows when that happens..
See attached patch (sorry, no git)

2 more suggestions for better readibility of the code:
- move the function nodeaccess_nodereference_field_delete_instance($instance) underneath the ..._update_instance()
- rename internal functions to _nodeaccess_nodereference_...() . This way it is easier to make the difference between hooks and own/internal functions.

johnv’s picture

Suppose a node type with node reference, but without NANR settings.
The code below invalidates the cache, which should not be necessary for a 'normal' node type.

function nodeaccess_nodereference_node_access_records($node) {
  $grants = array();
  $field_data = nodeaccess_nodereference_field_settings($node->type);
  if (!empty($field_data)) {
    ...  // <= Processes a node with relevant NANR settings
  }

  // Flag that the cache is not to be relied upon.
  variable_set('nodeaccess_nodereference_cache_needs_clear', TRUE); // <= Why is the cache invalid?

  return $grants;
}
johnv’s picture

We need these lines :

+     if (isset($prior_instance['settings']['nodeaccess_nodereference']) ) {
        $old_settings = nodeaccess_nodereference_reduce_variable($prior_instance['settings']['nodeaccess_nodereference']);
+     }
+     else {
+       $old_settings = FALSE;
+     }
      $new_settings = nodeaccess_nodereference_reduce_variable($instance['settings']['nodeaccess_nodereference']);

danielb’s picture

@#20 - because we don't know whether the grants have changed. NANR settings could have been enabled previously? If the node is saved or content access permissions are rebuilt, then that code will run.

danielb’s picture

Hmm maybe invalidating when the content type settings change is enough?
I dunno, it feels risky

danielb’s picture

Yes it is risky, because someone could hit a node between the content type being changed and the node being rebuilt, and the cache would be wrong after the rebuild.

danielb’s picture

Status: Needs review » Fixed

added code in #21

johnv’s picture

Status: Needs review » Needs work

I still get the following, using code of this morning:
Notice: Undefined index: unused in nodeaccess_nodereference_node_access_records() (line 507

johnv’s picture

and this:
Warning: Invalid argument supplied for foreach() in nodeaccess_nodereference_reduce_variable() (line 624 of

danielb’s picture

What is being passed into nodeaccess_nodereference_reduce_variable() to cause that foreach error? As far as I can see it should always be an array? Plus it goes through nodeaccess_nodereference_recursive_filter() earlier which also does a foreach?

danielb’s picture

johnv’s picture

recap:
#19: the attached patch for an update function is necessary, to clean up existing saved data and avoid messages.
#20: variable_set('nodeaccess_nodereference_cache_needs_clear', TRUE); is OK, according to #22-24, but I'm not convinced, yet.
#21: is solved with #25
#26: Notice: Undefined index: unused does not occur after activating the updated function, or resaving the field-data
#27-#28: Warning: Invalid argument supplied for foreach() idem
#29: if ($data['unused'] && isset($data['referenced'])) idem

johnv’s picture

I now see that my update function 7104 is too complicated, and may adopt the style of 7103.

danielb’s picture

what is idem?

danielb’s picture

Status: Needs work » Needs review

something like this?

<?php


/**
 * Reduce settings to essentials.
 */
function nodeaccess_nodereference_update_7104() {
  $new_data = array();
  $data = variable_get('nodeaccess_nodereference', array());

  variable_del('nodeaccess_nodereference');

  foreach ($data as $type => $type_data) {
    foreach ($type_data as $field => $field_data) {
      if (!empty($field_data)) {
        $new_settings = nodeaccess_nodereference_reduce_variable($field_data);
        nodeaccess_nodereference_field_settings($type, $field, $new_settings);
      }
    }
  }

  return "Reduced settings to essentials.";
}

?>
johnv’s picture

it's Latin, 'the same as', 'dito'

johnv’s picture

Seems OK, do you need me to test it?

1 typo: "Reduced settings to essentials."

johnv’s picture

Daniel, will you copy the changes to node access user reference?

danielb’s picture

that's not a typo, and yes I have created an issue in NAUR

danielb’s picture

Status: Needs review » Fixed

alright added that in

johnv’s picture

Status: Fixed » Needs work

Both in NANR and NAUR we need this :

-     $new_settings = nodeaccess_userreference_reduce_variable($instance['settings']['nodeaccess_XXXXreference']);
+     if (isset($instance['settings']['nodeaccess_XXXXreference'])) {
+       $new_settings = nodeaccess_userreference_reduce_variable($instance['settings']['nodeaccess_XXXXreference']);
+     }
+     else {
+       $new_settings = array();
+     }

An error occurs when you add a new XXXreference field and save without settings, or when you remove all settings from an existing field.

danielb’s picture

Status: Needs work » Fixed

made updates similar to this to both modules, cheers

johnv’s picture

Status: Fixed » Needs work

Daniel, thanx for the coöperation.

PS. You might want to synchronise the .info files, too.

Node access node reference 7.x-1.21+5-dev Provides per node access control with Node reference fields.
Node access user reference 7.x-3.8+3-dev Provides node access through user reference fields.

danielb’s picture

Status: Needs work » Closed (fixed)

I've updated the descriptions. Please don't reopen a fixed issue to add unrelated comments as I was unable to properly deal with this change here.