When a user adds a new vocabulary default to the admin form at admin/user/taxonomy_access/edit/x, access to nodes in that vocabulary is not updated. This is similar to the issue in #727648: Node access not updated on default change, but has a different cause. In taxonomy_access_defaults_update(), the list of nodes to be updated is assembled before changes are made to {term_access_defaults}. When the default is changed, this is irrelevant, because one record with the role id and vocabulary id is present either way. When a default is added, however, there is no record for the role/vocab in {term_access_defaults} until it is inserted.

CommentFileSizeAuthor
#3 tac_739739-3.patch1.96 KBxjm

Comments

xjm’s picture

I find myself wondering if there is even any reason for _taxonomy_access_get_nodes_for_vocabulary() to accept a role id as an argument, since the list of nodes in the vocabulary is the same regardless of whether we are concerned with a specific node or not. The only value of passing an rid would be to exclude nodes that are already controlled by a specific term in that role, which the function does not do at present anyway.

xjm’s picture

_taxonomy_access_get_nodes_for_vocabulary() is called in the following places:

  1. taxonomy_access_vocabulary_delete_submit(), without rid.
  2. taxonomy_access_admin_form_submit(), with rid, when one or more vocabulary defaults are deleted.
  3. taxonomy_access_defaults_update(), with rid, when a term default is updated.
xjm’s picture

Status: Active » Needs review
StatusFileSize
new1.96 KB

The attached patch modifies _taxonomy_access_get_nodes_for_vocabulary() so that, if an rid is specified, it uses this rid to exclude nodes with terms controlled in {term_access} for that role. This adds a second query with a potentially lengthy NOT IN () (we need to support MySQL 4 and so can't use subqueries), but the performance cost of this query is much smaller than updating even a handful of nodes unnecessarily.

If no rid is passed, the behavior is unchanged.

xjm’s picture

Seems to work properly; a full list of nodes in the vocabulary is returned when there is no rid or when the rid has no terms for the vocab configured; otherwise a subset is returned.

If a node is tagged with two terms from the vocabulary, one controlled in {term_access} and one not, the node is included in the returned list, which is the appropriate behavior (since a deny in the vocab default will override an allow for the controlled term in this situation).

keve’s picture

It is getting complicated. :) But the logic of it is brilliant.

xjm’s picture

I think this is actually what klance was trying to do in the ubiquitously-indicated #167977: Very slow updating category permissions and "access denied" on all pages until done, but the query wasn't quite right and so it wasn't returning anything.

xjm’s picture

Status: Needs review » Fixed

#3 committed to 6.x-1.x-dev:
http://drupal.org/cvs?commit=341022

Status: Fixed » Closed (fixed)

Automatically closed -- issue fixed for 2 weeks with no activity.