I'll start off by saying I'm not sure Views is the root cause of this problem. I'm also not sure how much information to give so there's a bit here.

It's taken me a while to narrow it down but there seems to be a problem with the access arguments in views' implementation of hook_menu_alter().

To replicate, install the modules views (latest dev) and admin_views (latest dev) and enable.

Visit any admin page and you should see the following errors:

Notice: Trying to get property of non-object in user_access() (line 807 of /drupal/modules/user/user.module).
Notice: Trying to get property of non-object in user_access() (line 819 of /drupal/modules/user/user.module).
etc.

admin/content gives "access denied" error, which is the problem path.

The second parameter of user_access() should be an object or nothing but in this case it's getting a string matching the first argument. This seems to occur because admin_views sets the "access arguments" which views adds to in views.module in the function views_menu_alter():

          // This item already exists, so it must be one that we added.
          // We change the various callback arguments to pass an array
          // of possible display IDs instead of a single ID.
          $callbacks[$path]['page arguments'][1] = (array)$callbacks[$path]['page arguments'][1];
          $callbacks[$path]['page arguments'][1][] = $display_id;
          $callbacks[$path]['access arguments'][] = $item['access arguments'][0];
          $callbacks[$path]['load arguments'][1] = (array)$callbacks[$path]['load arguments'][1];
          $callbacks[$path]['load arguments'][1][] = $display_id;

This adds to the ['access_arguments'] array so there are 2 items, in my case identical. This is then serialized in includes/menu.inc:

'access_arguments' => serialize($item['access arguments']),

The issue is user_access() doesn't take a serialized value so in includes/menu.inc the access_arguments are unserialized and passed to user_access() as 2 separate parameters:

    $arguments = menu_unserialize($item['access_arguments'], $map);
    // As call_user_func_array is quite slow and user_access is a very common
    // callback, it is worth making a special case for it.
    if ($callback == 'user_access') {
      $item['access'] = (count($arguments) == 1) ? user_access($arguments[0]) : user_access($arguments[0], $arguments[1]);
    }

This then leads to the "Trying to get property of non-object in user_access()" errors.

This patch sets the 'access arguments' to its existing value rather than adding to it. This may have other ramifications but I haven't come across any yet.

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

imclean’s picture

Possibly related:

#1422098: Trying to get property of non-object in user_access()

Early on I was also seeing the error in this issue but it seems to have disappeared:

#1739332: Contrib module admin_views breaks relation tab

Cache needs to be flushed after applying the above patch.

imclean’s picture

Status: Active » Needs review

Needs review.

imclean’s picture

Status: Needs review » Closed (works as designed)

Ok clearly if this really was a bug it'd be much more widespread than just me.

#1780004: Trying to get property of non-object in user_access() with 2 admin views on the same path

78doog’s picture

Thank you I had the same problem, and the patch worked for me.

danhooker’s picture

Had the same problem, the patch seems to have resolved it. Thanks.

sylus’s picture

Status: Closed (works as designed) » Needs review

Marking issue as needs review as other people have this problem.

kenorb’s picture

Detailed backtrace and reproducible steps available at:
https://drupal.org/node/1780004#comment-7849775

kenorb’s picture

Status: Needs review » Reviewed & tested by the community

Applied patch and cleared the cache. Seems to work.
I could access my broken view again.

drush sqlq 'SELECT * FROM menu_router WHERE access_callback = "user_access" AND access_arguments LIKE "a:2:%" \G'

should return nothing.

lathan’s picture

+1 patch seems to have cleared this issue for us we have had it for a very long time.

arnoldbird’s picture

The patch had no affect on the issue for me. I'm still seeing very large numbers of these notices whenever I hit any user page. (e.g. user, user/edit, etc). I have no particular reason to think it's a views bug in my case.

arnoldbird’s picture

My problem was that I overwrote $user. I assigned the result of entity_load('user', array($uid)) to $user instead of to $account.

arnoldbird’s picture

Issue summary: View changes

Confusing typo

dalejung’s picture

I tracked this down to two views trying to overtake the same path. Specifically commerce_backoffice has a admin/content view.

kerasai’s picture

I was receiving this error using Views 7.x-3.7, with VBO and Admin Views.

Cache clear fixed it.

dawehner’s picture

Issue summary: View changes

Given that this affects potentially every site we should try to write some test that this never happens again.

xbrianx’s picture

Version: 7.x-3.x-dev » 7.x-3.8

I am now getting this issue using the 3.8 version of views after installing admin views

MrHaroldA’s picture

Version: 7.x-3.8 » 7.x-3.x-dev
Status: Reviewed & tested by the community » Needs work

Needs tests!

GuGuss’s picture

Status: Needs work » Needs review
FileSize
736 bytes

This patch fixed the issue for me.

Here is a downgraded patch which applies on 3.8.

dawehner’s picture

@GuGuss
Are you sure we still need this patch in views itself? Afaik a patch in this area got committed already
with documentation and even a test.

GuGuss’s picture

@dawehner
Not sure what patch you're referring to? I'm using 3.8 and this patch fixed the notices so I guess I'll use it as it is ;-)

lmeurs’s picture

Though I have been using Views 3.8 and Administrations views for a while without problems, these errors started occuring after enabling Commerce Backoffice 1.9. I enabled Commerce Backoffice submodules Orders & Content at the same time, so do not know which one caused the error.

The patch from the OP views_access_arguments-0.patch works it for me so far. Thanks all!

EDIT: Both Commerce Backoffice Content and Administration views had a content view available at admin/content. After undoing the patch and disabling either of the views the problem was solved in my case.

kenorb’s picture

Status: Needs review » Reviewed & tested by the community

It's not commited yet to 7.x-3.x
See: http://cgit.drupalcode.org/views/tree/views.module

joelpittet’s picture

Yes this patch #17 still applies, and fixes the user_access notices.

But strange my views -dev release as of today is reporting 7.x-3.7+35-dev and it should likely be 7.x-3.8...?
Maybe the 3.8 didn't get a release or something?

joelpittet’s picture

https://www.drupal.org/node/608852
Shows the same, so not my drush pulling it down wrong.

dawehner’s picture

This basically totally drops the existing access argument, do we really want to do this?

joelpittet’s picture

Status: Reviewed & tested by the community » Needs work
+++ b/views.module
@@ -433,7 +433,7 @@ function views_menu_alter(&$callbacks) {
-          $callbacks[$path]['access arguments'][] = $item['access arguments'][0];
+          $callbacks[$path]['access arguments'] = $item['access arguments'];

@dawehner Likely not. Could we just check if [0] index exists before we try to append it?

if (isset($item['access arguments'][0])) {
  $callbacks[$path]['access arguments'][] = $item['access arguments'][0];
}
recrit’s picture

JvE’s picture

I think that the same mechanism that defines which view/display gets shown on that path should be used to determine which access argument is used.

If two views specify the same path with different permissions, what should the access_arguments be?

Edit: It looks to me that the code in views_menu_alter() was never intended to deal with multiple views using the same path. Only with multiple displays within the same view using the same path.

dawehner’s picture

I'm a bit uncomfortable without having at least proper test coverage here.

das-peter’s picture

Status: Needs work » Needs review
FileSize
892 bytes

To me it looks like the current code in views_plugin_display_page::execute_hook_menu() ensures that $access_arguments[0] always is an array.
If you change e.g. the access plugin views_plugin_access_perm::get_access_callback() to not return an array of permissions the whole thing still fails - replacing the perm string by an empty array.
Now, instead fiddling with the quite complex views_plugin_display_page::execute_hook_menu() why don't we adjust views_check_perm() instead?
Change the way it operates to meet how views_check_roles() works?
Attached patch changes views_check_perm() to handle the given permission as an array - processing it with OR. Which means if there's a single permission that allows access TRUE is returned.
If the given $perms parameter isn't an array it is wrapped - this should ensure backward compatibility.
With this changes we might even able to extend the access plugin and allow to select multiple permissions.

JvE’s picture

@das-peter: the issue occurs when the menu item is inserted into the menu_router table (by views_menu_alter()) where the access_callback is set to "user_access" while the access_arguments is set to an array with multiple permissions.
views_check_perm() doesn't seem to enter the equation.

JvE’s picture

Status: Needs review » Needs work
das-peter’s picture

Status: Needs work » Needs review

@JvE views_plugin_display_page::execute_hook_menu() which is used by views_menu_alter() can, by default, use one of the following plugins:

  • views_plugin_access.inc
  • views_plugin_access_none.inc
  • views_plugin_access_perm.inc
  • views_plugin_access_role.inc

None of those plugins returns user_access as access callback. I just can assume that if you end up with the access callback user_access that something goes wrong somewhere else.
One common issue I know about is with admin_views, it provides the display views_plugin_display_system (which uses user_access) - now if you've multiple active displays for the same system path you likely end up with a messed up access arguments array - since the arguments are merged and not replaced when altering the menu items (this is due the way how drupal_alter() is implemented).

I usually use something like this to disable such system displays provided by modules, once I switch to a customized view:

/**
 * Implements hook_views_default_views_alter().
 */
function hook_views_default_views_alter(&$views) {
  // Disable some default views of modules in favour of our own ones.
  $view_is_enabled = array(
    'admin_views_node' => FALSE,
  );

  foreach ($view_is_enabled as $view_name => $status) {
    if (isset($views[$view_name])) {
      $views[$view_name]->disabled = !$status;
      foreach ($views[$view_name]->display as $display_id => $display) {
        $display->display_options['enabled'] = $status;
      }
    }
  }
}
JvE’s picture

Thank you for the explanation.
But isn't this whole issue about a messed up access arguments array due to having multiple active displays for the same system path?

das-peter’s picture

Oh if so I guess I've hijacked an issue. ;)
However, this likely means that we would need to find a strategy to handle paths that are declared twice.
I could imagine to cache what's handled already, then drop duplicated declarations and use watchdog to let the admin know about the issue.

dawehner’s picture

However, this likely means that we would need to find a strategy to handle paths that are declared twice.

Well, there is actually the scope of admin_views, which provides a custom plugin to override path, which, ideally, should handle it better.

I agree that this patch of peter is a good workaround for many of the potential issues in this issue. In general its better safe to be than sorry. It could be easily the case that passing an array to user_access() accidentally returns TRUE.

I would be fine with committing as it is. It has some documentation why it handles both cases, which is really nice.
@jve Would you disagree with that entirely? I think we can leave the issue open to find a proper solution

  • dawehner committed 4ae3353 on authored by das-peter
    Issue #1771140 by imclean, das-peter, GuGuss: view_menu_alter() adding...
dawehner’s picture

Oh well I decided to just commit it. Let's continue with the other part of the issue :)

Dane Powell’s picture

Some housekeeping:

  • There are two patches in this issue, #17 and #29. #29 doesn't seem to address the original issue, but was committed anyway. #17 has not been committed- I'm marking that as displayed so that it's clear that it's under review.
  • I was experiencing this problem with admin_views and #17 fixed it for me. It looks simple enough, I'd vote to RTBC and close this rather long-running issue.
  • I think a lot of people are coming here after installing admin_views. Here is the corresponding issue that was originally in the admin_views queue and later moved to views and closed as a duplicate: #1780004: Trying to get property of non-object in user_access() with 2 admin views on the same path. I'm moving it back to admin_views for clarity.
imclean’s picture

A couple of things:

  1. The original patch is at #0, the one at #17 is against a release version (3.8) rather than git, which isn't useful for getting things committed.
  2. After reading this issue, I'm not completely sure it's the correct way to go. Why was Views written like this in the first place? Are multiple access arguments supported? Should they be? What's the correct way to override paths?
rooby’s picture

The patch in #17 fixes the errors and missing menu items for me.

I don't know enough about the issue to judge whether or not it is the best solution.

hkovacs’s picture

patch #17 fixed it for me on Views Version: 7.x-3.14

GoddamnNoise’s picture

The patch in #17 fixed the errors and missing menu items for me using Views 7.x-3.14.

amjad1233’s picture

Anyone looking for the same patch with views 7.x-3.20.

Please find the patch.

Regards,
Amjad

GoddamnNoise’s picture

It seems the patch stopped working after yesterdays' new Views release (7.x-3.21) and it's happening again.

DamienMcKenna’s picture

Running the tests on #43..

GoddamnNoise’s picture

The patch on #43 is really the same as the patch on #7, so the patch on #43 should stop working too after the 7.x-3.21 Views release.

kporras07’s picture

DamienMcKenna’s picture

Thanks, but #43 didn't need a reroll.

ljgra’s picture

No patched worked. I had to downgrade views to 7.21, now my site is back to normal. But I want my views updated, however I am currently having this massive headache of the issue kept on coming back. This could be triggered by other modules perhaps disabled/enable but I just could not identify which.

DamienMcKenna’s picture

FYI If you're still seeing this problem and you use admin_views, please test the current dev version of admin_views too.

Failing that, I think debugging which view causes the problem would be useful, there might be other contrib modules which trigger the bug.

DamienMcKenna’s picture

Status: Needs review » Fixed

Committed. Thank you all.

DamienMcKenna’s picture

Status: Fixed » Needs review

Oh wait, sorry, I committed the other issue. X-)

ckng’s picture

Status: Needs review » Reviewed & tested by the community

Patch #47 get rids of all the PHP notices.

DamienMcKenna’s picture

Status: Reviewed & tested by the community » Fixed
Parent issue: » #3118500: Plan for Views 7.x-3.25

Committed. Thank you.

imclean’s picture

Haha...wow! So the exact change I provided a patch for in #0 in 2012 has been committed, 8 years later!

There has been a bit of discussion which is useful.

Status: Fixed » Closed (fixed)

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