Support desk blog: How to collect organization / household information via drupal's "My Account"

Published
2009-06-19 11:45
Written by
Support desk blog: How to collect organization / household information via drupal's "My Account" This blog post is courtesy of IRC user (huf, Mihaly Berenyi). The question is how do you get a permisioned user to edit organization information from the Drupal My Account Page. The answer surprising is quite simple :)
  • Create an organization profile and check "My Account" in the used for settings
  • Ensure that the user's relationship with the organization is permissioned, i.e. the user has the permission box checked to edit the organization
  • Apply the patch at the end of this post
huf modified the civicrm.module file to check if a profile is of type organization. If it is, he checks if the user has any permissioned organization and if so, switches the contact ID around and loads the organization data. The profile code does the rest of the work and updates the organization record. We can apply the same principle to expose and allow users to update their household record A few things still need to be done:
  • Handle the view case and display the organization profile data
  • Handle the case where a user is permissioned for multiple organization(s). We could potentially do this by introducing more tabs into the screen dynamically. (some drupal magic needed here)
  • Extend the code to handle households

Index: civicrm.module
===================================================================
@@ -485,9 +485,12 @@
     $weight = 100;
     foreach ($allUFGroups as $key => $value) {
         if ( $value['is_active'] ) {
-            $ufGroups[] = array( 'name'   => $value['name'],
-                                 'title'  => $value['name'],
-                                 'weight' => $weight );
+            $ufGroups[] = array(
+                                'name'   => $value['name'],
+                                'title'  => $value['name'],
+								'group_type' => $value['group_type'],
+                                'weight' => $weight
+                                );
             $weight += 10;
         }
     }
@@ -541,27 +544,34 @@
 {
     require_once 'CRM/Core/BAO/UFMatch.php';
     require_once 'CRM/Core/BAO/UFGroup.php';
+	require_once 'CRM/Contact/BAO/Relationship.php';
 
     // lets suppress key generation for all CMS forms
     civicrm_key_disable( );
 
+    $is_org_cat = _civicrm_is_org_cat($category, $user);
+
     $output = array( );
 
-    $userID = CRM_Core_BAO_UFMatch::getContactId( $user->uid );
-    if ( ! $userID ) {
+    $contactID = CRM_Core_BAO_UFMatch::getContactId( $user->uid );
+    if ( ! $contactID ) {
         $ctype = civicrm_get_ctype( 'Individual' );
         CRM_Core_BAO_UFMatch::synchronize( $user, false, 'Drupal', $ctype );
-        $userID = CRM_Core_BAO_UFMatch::getContactId( $user->uid );
+        $contactID = CRM_Core_BAO_UFMatch::getContactId( $user->uid );
     }
 
     // at this point we better have a valid userID
-	if ( ! $userID ) {
+    if ( ! $contactID ) {
         // we get into this scenario if we do not like the email address supplied by the user
         return;
     }
 
-    $ctype = CRM_Core_DAO::getFieldValue( 'CRM_Contact_DAO_Contact', $userID, 'contact_type' );
+    if ($is_org_cat) {
+        $contactID = _civicrm_find_related_org($contactID, $org_data, intval(@$_GET['ofs']));
+    }
 
+    $ctype = CRM_Core_DAO::getFieldValue( 'CRM_Contact_DAO_Contact', $contactID, 'contact_type' );
+
     //to allow Edit any profile if user have permission
     $profileID = CRM_Core_DAO::getFieldValue( "CRM_Core_DAO_UFGroup", $category, 'id', 'title' );
     require_once 'CRM/Core/Permission.php';
@@ -569,20 +579,23 @@
     
     if ( in_array($profileID, $ufGroupIDs) ) {
         // get all the data for this specific category
-        $html = CRM_Core_BAO_UFGroup::getEditHTML( $userID, $category, null, false, $reset, null, $doNotProcess, $ctype );
+        $html = CRM_Core_BAO_UFGroup::getEditHTML( $contactID, $category, null, false, $reset, null, $doNotProcess, $ctype );
     } else {
         CRM_Core_Error::fatal( ts( 'The requested Profile (gid=%1) is disabled OR it is not configured to be used for \'Profile\' listings in its Settings OR there is no Profile with that ID OR you do not have permission to access this profile. Please contact the site administrator if you need assistance.',
                                    array( 1 => $profileID )));
     }
-    
+
     if ( $html ) {
+        if ($ctype == 'Organization') {
+            $html = '

'.$org_data[$org_offset]['name'].'

'.$html; + } + //$html = civicrm_add_jquery( $html ); $index = empty( $category ) ? 'civicrm-profile-my-account' : $category; $output[$index][] = array( '#title' => $category, '#value' => $html, '#weight' => 1 ); } - return $output; } @@ -673,6 +686,13 @@ // check for either user/register or admin/user/user/create $register = ( arg(1) == 'register' || arg(3) == 'create' ) ? true : false; $userID = CRM_Core_BAO_UFMatch::getContactId( $user->uid ); + + // rewrite the cid, funky! + $is_org_cat = _civicrm_is_org_cat($title, $user); + if ($is_org_cat) { + $userID = _civicrm_find_related_org($userID, $_dummy = null, intval(@$_GET['ofs'])); + } + $errors = CRM_Core_BAO_UFGroup::isValid( $userID, $title, $register ); if ( is_array( $errors ) ) { if ( $register ) { @@ -792,3 +812,43 @@ function civicrm_add_jquery( &$html ) { return $html . ''; } + +function _civicrm_is_org_cat($category, &$user) { + $categories = civicrm_categories($user); + $is_org_cat = false; + foreach ($categories as $c) { + if ($c['name'] == $category) { + if (strpos($c['group_type'], 'Organization') !== false) { + $is_org_cat = true; + } + break; + } + } + return $is_org_cat; +} + +function _civicrm_find_related_org($contactID, &$org_data, $org_offset = 0) { + // we have the user, get his relations, and maybe we need to ditch this loser + $currentRelationships + = CRM_Contact_BAO_Relationship::getRelationship( + $contactID + ); + $org_data = array(); + foreach ($currentRelationships as $cr) { + // does the user have permission to edit the org + if ($cr['is_active'] and $cr['is_permission_a_b']) { + $org_data[] = array( + 'id' => $cr['cid'], + 'name' => $cr['name'], + ); + } + } + + // which org to display? + if (isset($org_data[$org_offset])) { + $contactID = $org_data[$org_offset]['id']; + } + + return $contactID; +} +
Filed under

Comments

Sounds like an exciting development

Can it (easily) be extended so that it can also be applied to particular relationships 'Indiv to Indiv' eg so we can nominate a 'main contact' at an organisation, apply a relationship to connect those people 'contact for/is' and thereby have access to specified fields via a profile - or will this fail because the structure requires a drupal tab for each individual - i guess this is the same question you have above about it handling people who have more than one organisation.

So perhaps rather than thinking of a tab per each, we think of a single tab with an exposed filter, where the options in the filter are 'all organisations/individuals the person has permission for'. Then they can basically dial up the person involved.

May have some time to help such a solution as it sounds as if it might sidestep an ACL Hook approach.

Anonymous (not verified)
2009-06-22 - 08:28

Now if only it could tie in with the request at:
http://forum.civicrm.org/index.php/topic,5520.msg34385.html#msg34385

"Using Employees address as mailing address for Individual"

This is indeed very cool, and opens up a great link between Drupal and CiviCRM without opening the full dashboard to users. Very nice!

Cheers Lobo, this looks interesting.

I can see how it matches some use cases (something similar happens with Drupal Association where my individual Drupal user is attached to both my individual CiviCRM and organisational CiviCRM contact records).

However, for larger organisational use, it seems like it might be confusing to locate organisational information on the My Account page for a particular user? For an Org with a dozen employees in the system, it might not be obvious which employee to log in as in order to update the Org's details ...

Regarding the code above, is this something which needs to be implemented via a patch to civicrm.module, or can it be done by adding profiles via a separate module to keep the core CiviCRM code clean? Also, the patch formatting is a bit funky for me in one place (although it does work OK if you copy the code from the HTML source). I see a single line in large green text midway thru the patch code.

Thanks Lobo and Mihaly Berenyi!

Anonymous (not verified)
2009-11-10 - 09:36

I had applied this to 3.0.1 and it worked.

Any plans to maintain this either as very useful patch or in core?

Also how do I get text area content to display with/without the Drupal FCKEditor that I have installed - CiviCRM needs to pass more info than just the content.

For now, we are not maintaining the above patch. This was contributed by someone else but was quite cool and hence we blogged about it

lobo