I've been using some of the functions available in CiviNode for a custom module I'm building. I ran into a permission issue the other day, and I found myself having trouble displaying an error message to the screen. For my project, Anonymous users do not have access to View All Contacts yet I want to display my "Board of Directors" group on a page in my Drupal site for everyone to view.
Here's my code:
$list = civinode_util_group_contacts($group_id, $start = 0, $num_recs = 0);
foreach($list as $member) {
$contact = civinode_util_load_cdata($member, $pid = 5);
A call to civinode_util_group_contacts() returned an array of NULL values when an Anonymous user views my "Board of Directors" page. Maybe it should not do that, but with an array of NULL values and no error message it's not easy to write a clean check of the $list array before running a foreach.
So I start my foreach and loop through these NULL values. Passing a NULL to civinode_util_load_cdata() returns an error object with two error messages:
[message] => 22 contacts matching input params.
[message] => You do not have permission to access group with id:
Both are listed as Fatal errors. I'm not sure why the first one is an error, but what I really want to grab and display on the screen is the second one about permissions.
I noticed a couple of things in civinode_utils.inc.
1. In function &_civinode_get_last_error(), the last error is assigned to $lastError on line 185, but the function returns variable $last_error.
//For now, let's see how "deep the rabbit hole goes" and
//return just the tip of the stack.
if ($error_stack->hasErrors()) {
$errors = $error_stack->getErrors();
$lastError = array_pop($errors);
}
return $last_error;
}2. function &_civinode_get_last_error() does what I want (if the variable name is changed to $last_error), but I think it would be better if I could use civinode_get_last_error(). Like so:
$contact = civinode_util_load_cdata($member, $pid = 5);
if(civinode_check_error($contact)) {
$err = civinode_get_last_error();
print $err['message']; // just keeping it simple here
}In order for this code to work above requires some changes to civinode_check_error()
From:
(starts after the //Docs are wrong comment)
if($obj and is_a($obj, 'CRM_Core_Error')){
$msg = $obj->_errors[0]['message'];
_civinode_set_error($msg);
if (!$log_error)
to
if($obj and is_a($obj, 'CRM_Core_Error')){
_civinode_set_error(_civinode_get_last_error());
if (!$log_error)
I wasn't sure how these changes might affect the rest of the module, so I thought I'd bring it up here first
| Comment | File | Size | Author |
|---|---|---|---|
| #2 | issue-157103-0.patch | 4.47 KB | Torenware |
Comments
Comment #1
Torenware commentedrobeano,
Some good catches on your part, first of all.
I'm going to do this in stages. First, try this code for civinode_util_group_contacts() instead:
This code *should* allow you to do what you want: show contacts to the anonymous user, as long as you've set up permissions so that the anonymous user has access rights to the group. This code also works for smart groups, which the old code never did. It also should not return an error, since if a group does not exist, it will simply return no contacts.
If it fails, it's a permissions issue within CiviCRM itself, and you or I will need to log an issue in JIRA against 1.7.
I'm looking at the rest of your issues now as well, and will add a comment when I'm through them.
Comment #2
Torenware commentedAs for the error handling related issues:
1) You're completely correct about the $lastError and $last_error business. Fixed.
2) I like the fact that civinode_get_last_error() returns a string, but I see your point. So here's what I propose:
I'm posting this as a patch. Try it out, and if it works for you, I'll check it in and create a new packages tag for it.
Comment #3
robeano commentedThanks Tokenware!
The new civinode_util_group_contacts() works great.
To respond to your second post, specifically #2), I don't actually need the object either and I like the idea of civinode_get_last_error() returning a string too. Thanks for taking it a step further.
The new civinode_get_last_error_object() is a good addition, but I'll probably just use your new civinode_get_last_error(). All I wanted was to make sure I could capture the permission error not just the first error returned.
I'm trying your patch now.
Comment #4
robeano commentedOops I mean Torenware! Sorry about that. :)
Comment #5
Torenware commentedI was mostly worried about the change to the groups code (due to the bug you found, the old error reporting code clearly never worked anyway), so I'm going to complete the check-in.
Thanks for giving the code a good looking over. I've generated a 5.x-1.1 version, and it should be up in a couple of minutes.
Rob
Comment #6
robeano commentedPatch works well. Thanks for updating the code so quickly.