CiviCRM Community Forums (archive)

*

News:

Have a question about CiviCRM?
Get it answered quickly at the new
CiviCRM Stack Exchange Q+A site

This forum was archived on 25 November 2017. Learn more.
How to get involved.
What to do if you think you've found a bug.



  • CiviCRM Community Forums (archive) »
  • Old sections (read-only, deprecated) »
  • Developer Discussion »
  • APIs and Hooks (Moderator: Donald Lobo) »
  • First Custom Drupal Module Using a CiviCRM Hook Works!
Pages: [1] 2

Author Topic: First Custom Drupal Module Using a CiviCRM Hook Works!  (Read 7455 times)

FatherShawn

  • Ask me questions
  • ****
  • Posts: 372
  • Karma: 25
    • C3 Design
  • CiviCRM version: 4.2.11
  • CMS version: Drupal 7.23
  • MySQL version: 5.5.32
  • PHP version: 5.3.10
First Custom Drupal Module Using a CiviCRM Hook Works!
February 26, 2010, 07:49:59 am
Hi gang!  I'm working my way through a Drupal/Civi project as a way of learning Drupal, php and more about Civi.  The project is to manage the information and CRM for an episcopal election process.  I'd like to collect contact info via a profile from applicants for their references and create a relationship between the applicant (acting user) and the reference (contact created) when the profile is saved.

I've read through the API & Hook documentation and found civicrm_relationship_create in the API's.  So can I use hook_civicrm_postProcess to add custom function to contact creation via a profile or is there a better way?
« Last Edit: March 04, 2010, 06:44:16 am by FatherShawn »
Lead Developer, C3 Design.
Twitter: @FatherShawn

Donald Lobo

  • Administrator
  • I’m (like) Lobo ;)
  • *****
  • Posts: 15963
  • Karma: 470
    • CiviCRM site
  • CiviCRM version: 4.2+
  • CMS version: Drupal 7, Joomla 2.5+
  • MySQL version: 5.5.x
  • PHP version: 5.4.x
Re: Inching my way into the API's, Hooks, and Drupal
February 26, 2010, 08:17:09 am

that seems to be a good way to go about doing things :)

lobo
A new CiviCRM Q&A resource needs YOUR help to get started. Visit our StackExchange proposed site, sign up and vote on 5 questions

FatherShawn

  • Ask me questions
  • ****
  • Posts: 372
  • Karma: 25
    • C3 Design
  • CiviCRM version: 4.2.11
  • CMS version: Drupal 7.23
  • MySQL version: 5.5.32
  • PHP version: 5.3.10
Re: Inching my way into the API's, Hooks, and Drupal
February 26, 2010, 08:22:34 am
Great!  Thanks for the quick reply!!  When I get stuck, I wanted to know that it wasn't because I jumped off the wrong cliff at that start.  ;)
Lead Developer, C3 Design.
Twitter: @FatherShawn

Eileen

  • Forum Godess / God
  • I’m (like) Lobo ;)
  • *****
  • Posts: 4195
  • Karma: 218
    • Fuzion
Re: Inching my way into the API's, Hooks, and Drupal
February 26, 2010, 10:44:12 am
Hi Father Shawn,

This is the code for a module we wrote to change the current employer relationship created on sign-up. The form is fired on the Drupal create user form & changes the relationship with the current employer (that is created anyway) to be one whereby the employer has permission to edit the new user. There is also a membership tweak that is probably redundant by version 3.1.x

We have also tweaked the code so that if a user (e.g. an secretary) has permission over an Organisation and that organisation has permission over another user the first user inherits the companies permissions over the second user. We have only implemented this for current employer but arguably this is the only way giving an org permission over an individual makes sense.


Code: [Select]
<?php

function fuzion_relationships_help( $section ) {
switch ($section) { 
case 'admin/help#fuzion_relationships':
        return 
t( ' This function changes the current employer relationship created on sign-up
 to be one where the employer has permission to edit the contact. Combined with 
  an edit to permissions.php this allows the company administrator (who has
  permissions over the company) to edit the employees of the company.
  Also there is a tweak for ensuring inherited memberships are created (
  which may not happen automatically depending on the CiviCRM version and who has permissions
  to access CiviMember ' 
);

    case 
'admin/modules#description':
        return 
t( 'fuzion_relationships module v0.01' );

    }
}
/*
/**
 * This function changes the current employer relationship created on sign-up
 * to be one where the employer has permission to edit the contact. Combined with 
 * an edit to permissions.php this allows the company administrator (who has
 * permissions over the company) to edit the employees of the company.
 * Also there is a tweak for ensuring inherited memberships are created (
 * which may not happen automatically depending on the CiviCRM version and who has permissions
 * to access CiviMember
 *
 */
function fuzion_relationships_civicrm_postProcess( $formName, &$form ) {

if ( $formName == 'CRM_Profile_Form_Dynamic' ) {
civicrm_initialize( true );
$data = get_object_vars($form);
$mode = $form->getVar('_mode');
require_once('api/v2/Relationship.php');
//ie. this contactID is the person submitting the form
                
$contactID = $form->getVar( '_id' );
                
$employer = $data['_submitValues']['current_employer'];
                
// get the employer contactID
                
$params = array(
                    
'return' => 'id',
                    
'sort_name' => $employer, 
                    
'contact_type'=> 'Organization'
);
//translate employer name into employer ID as Id doesn't seem to be 
//passed in
require_once('api/v2/Contact.php');
                
$apiSearch=(array_values( civicrm_contact_search(&$params)));
                
$employerID = (($apiSearch[0]['contact_id']));
                
                
// we are updating the relationship that has already been created
                // so that the company will have edit permissions over the employee
                // we need the relationship ID to do this but we haven't been given it 
                // in the form so we need to get it
                
$relationshipParams['contact_id'] = $contactID;
                
$relationshipParamsb['contact_id'] = $employerID;
                
$outputParams =   civicrm_contact_relationship_get($relationshipParams , $relationshipParamsb); 
                
$relationshipID = implode(array_keys($outputParams['result']));

                foreach (
$outputParams['result'] as $relationshipID -> $value)   {    
            
$params = array('contact_id_a' => $contactID,
                     'contact_id_b' => $employerID,
            
    'relationship_type_id' => 4,
            
    'is_permission_b_a' => 1,
                                
'is_active' => 1,          
            
                 'id' =>  $relationshipID);
                }
// this is where the relationship is updated
           $newrels = civicrm_relationship_create($params);
   /* here we are forcing the relationship based membership to be updated
   * the membership is not based automatically on sign-up as anonymous
   * user doesn' have permission to do that.
   * this is likely to be fixed soon
   * http://issues.civicrm.org/jira/browse/CRM-5551
    */
   
           $ids['contactTarget'] = $employerID ;
           require_once('CRM/Contact/BAO/Relationship.php');
       CRM_Contact_BAO_Relationship::relatedMemberships( $contactID, $params, $ids,CRM_Core_Action::ADD  );
           
        return;
}

   
}



NOTE the reason this is useful for us is we have tweaked Contact_BAO_Contact_Permission.php to allow 'transitive permissions' - here is the revised function


Code: [Select]
    static function relationship ( $selectedContactID, $contactID = null )
    {
   
        $session   =& CRM_Core_Session::singleton( );
        if ( ! $contactID ) {
            $contactID =  $session->get( 'userID' );
            if ( ! $contactID ) {
                return false;
            }
        }
        if (  $contactID == $selectedContactID ) {
            return true;
        } else {
         
          //get relationships between given contact IDs where $contactID
          // has permission over the $selectedContactID
         $query = "
SELECT id
FROM   civicrm_relationship
WHERE  ( contact_id_a = %1 AND contact_id_b = %2 AND is_permission_a_b = 1 ) OR
       ( contact_id_a = %2 AND contact_id_b = %1 AND is_permission_b_a = 1 )
 
";
            $params = array( 1 => array( $contactID        , 'Integer' ),
                             2 => array( $selectedContactID, 'Integer' ) );
            //Fuzion edit starts
            //if contact has edit permission over related contact return true             
            $result =  CRM_Core_DAO::singleValueQuery( $query, $params );

            if ($result){
            return $result;
                   
            }else{
                /* otherwise check for a transitive relationship - i.e. one where they
                * have edit over the employer & the employer has edit over another
                * contact. NB it is difficult to see how else you would apply an
                * employer having permission as they don't log on.
                */

                $contactIds = array($contactID);
require_once('CRM/Contact/BAO/Relationship.php');
            $employer = CRM_Contact_BAO_Relationship::getCurrentEmployer($contactIds);
if($employer[$contactID ][org_id] ){
                $params = array( 1 => array( $contactID        , 'Integer' ),
                                  2 => array( $employer[$contactID ][org_id] , 'Integer' ) );
                                                         
                //does contact have permission to edit their own employer? If not return false   
                // if so proceed to next check             
                $result =  CRM_Core_DAO::singleValueQuery( $query, $params );
}

                if (!$result){
                return $result;
                       
                }else{
               
                     //does contact's employer have permission to edit the secondary contact?
                    //if not return false
                    $params = array( 1 => array( $employer[$contactID ][org_id]       , 'Integer' ),
                                 2 => array( $selectedContactID, 'Integer' ) );
                    $result =  CRM_Core_DAO::singleValueQuery( $query, $params );
   
                    return $result;
             
                }
            }
           
           
            }
        }
   
Make today the day you step up to support CiviCRM and all the amazing organisations that are using it to improve our world - http://civicrm.org/contribute

Eileen

  • Forum Godess / God
  • I’m (like) Lobo ;)
  • *****
  • Posts: 4195
  • Karma: 218
    • Fuzion
Re: Inching my way into the API's, Hooks, and Drupal
February 26, 2010, 10:51:58 am
Here's the content of .info - just adding it since you are new to drupal modules from your comment

Code: [Select]
; $Id$
name = Fuzion Modules for civiCRM- relationships
description = Edits the permissions on a new employee signing up so that the company has edit permission over them.
package = CiviCRM
dependencies[] = civicrm
core = 6.x
Make today the day you step up to support CiviCRM and all the amazing organisations that are using it to improve our world - http://civicrm.org/contribute

FatherShawn

  • Ask me questions
  • ****
  • Posts: 372
  • Karma: 25
    • C3 Design
  • CiviCRM version: 4.2.11
  • CMS version: Drupal 7.23
  • MySQL version: 5.5.32
  • PHP version: 5.3.10
Re: Inching my way into the API's, Hooks, and Drupal
February 27, 2010, 09:25:55 am
Thanks, Eileen.  Very thoughtful.

I've actually written my first little Drupal module to inject the proper code into two custom CCK fieldgroups so that they work with Vertical Tabs module. 

I'm really grateful for your code example for the API usage :)
Lead Developer, C3 Design.
Twitter: @FatherShawn

FatherShawn

  • Ask me questions
  • ****
  • Posts: 372
  • Karma: 25
    • C3 Design
  • CiviCRM version: 4.2.11
  • CMS version: Drupal 7.23
  • MySQL version: 5.5.32
  • PHP version: 5.3.10
Re: Inching my way into the API's, Hooks, and Drupal
March 01, 2010, 06:42:18 pm
OK, so if I understand this code, you are creating a relationship between the acting user and an employer.  I want to create a relationship between the acting user and the contact created by the profile submission.  So if
Code: [Select]
<?php
$contactID 
= $form->getVar( '_id' );
Accesses the id of the user submitting the form, is there easy access to the id of the contact created by the form?

Is there documentation on the data structure for profile submissions?
Lead Developer, C3 Design.
Twitter: @FatherShawn

Donald Lobo

  • Administrator
  • I’m (like) Lobo ;)
  • *****
  • Posts: 15963
  • Karma: 470
    • CiviCRM site
  • CiviCRM version: 4.2+
  • CMS version: Drupal 7, Joomla 2.5+
  • MySQL version: 5.5.x
  • PHP version: 5.4.x
Re: Inching my way into the API's, Hooks, and Drupal
March 01, 2010, 07:10:47 pm
Quote from: FatherShawn on March 01, 2010, 06:42:18 pm
Is there documentation on the data structure for profile submissions?

the data structure for most civicrm objects corresponds to the schema of that object. so check the DB schema for more details


lobo
A new CiviCRM Q&A resource needs YOUR help to get started. Visit our StackExchange proposed site, sign up and vote on 5 questions

FatherShawn

  • Ask me questions
  • ****
  • Posts: 372
  • Karma: 25
    • C3 Design
  • CiviCRM version: 4.2.11
  • CMS version: Drupal 7.23
  • MySQL version: 5.5.32
  • PHP version: 5.3.10
Re: Inching my way into the API's, Hooks, and Drupal
March 03, 2010, 11:57:12 am
Here's where I am with my code:
Code: [Select]
<?php
function reference_relate_discerning_civicrm_postProcess( $formName, &$form ) {

  
$mode = $form->getVar('_mode');     /* Integer */
  
$profile_id = $form->getVar('_gid'); /* String */
  
if ( $formName == 'CRM_Profile_Form_Edit' and 
       
$profile_id=='9' and
       
$mode==4) {
    
civicrm_initialize( true );
    
/*Get session data - CRM_Core_Session doesn't initiate a session of one already exists */
    
$session =& CRM_Core_Session::singleton( );
    require_once(
'api/v2/Relationship.php');
    
/* I believe that this is the contact created by the form */
    
$reference_contactID = $form->getVar( '_id' );
    
$acting_user_contactID = $session->get( 'userID' );
    
/* Set up the parameters */
    
$params = array('contact_id_a' => $acting_user_contactID,
                    
'contact_id_b' => $reference_contactID,
                    
'relationship_type_id' => 10,
                    
'is_active' => 1,
                    
'start_date' => array('d'=>idate(d),'M'=>idate(m),'Y'=>idate(Y)));
    
$created_result = civicrm_relationship_create($params);
    if ( 
civicrm_error ( $result )) {
      return 
$created_result['error_message'];
      } 
    else {
      return 
$created_result['id'];
      }
    }  
}

But it doesn't work because the Relationship definition expects Contact a to be of the Individual sub-type Applicant and Contact b to be of individual contact sub-type Reference.  I set up the sub-types to avoid having custom data on all individual records that only pertain to a certain subset.

Both contacts will be created by a profile.  There doesn't seem to be a profile setting for "create this subtype", so I guess I need to look for a hook and override the creation to add the subtype?
Lead Developer, C3 Design.
Twitter: @FatherShawn

FatherShawn

  • Ask me questions
  • ****
  • Posts: 372
  • Karma: 25
    • C3 Design
  • CiviCRM version: 4.2.11
  • CMS version: Drupal 7.23
  • MySQL version: 5.5.32
  • PHP version: 5.3.10
Re: Inching my way into the API's, Hooks, and Drupal
March 04, 2010, 06:42:46 am
IT WORKS!

Contact sub-types inherit fields from their parent, so switching first name and such fields from individual to applicant in the field definitions did the trick and the code that should work, actually does!
Lead Developer, C3 Design.
Twitter: @FatherShawn

petednz

  • Forum Godess / God
  • I’m (like) Lobo ;)
  • *****
  • Posts: 4899
  • Karma: 193
    • Fuzion
  • CiviCRM version: 3.x - 4.x
  • CMS version: Drupal 6 and 7
Re: First Custom Drupal Module Using a CiviCRM Hook Works!
March 04, 2010, 08:38:26 pm
This sounds like a really useful contribution. If I understand it this code (or at least the hook) means a Profile could be used for someone who is signing up for something (info, event, membership?) and the above could be used to let them add a contact for someone eg child, c-habitant, team mate, so that the other contact is also created and the relationship is created on the fly (with the potential from Eileen's code to then also force permissions etc)
Sign up to StackExchange and get free expert advice: https://civicrm.org/blogs/colemanw/get-exclusive-access-free-expert-help

pete davis : www.fuzion.co.nz : connect + campaign + communicate

Erik Hommel

  • Forum Godess / God
  • I live on this forum
  • *****
  • Posts: 1773
  • Karma: 59
    • EE-atWork
  • CiviCRM version: all sorts
  • CMS version: Drupal
  • MySQL version: Ubuntu's latest LTS version
  • PHP version: Ubuntu's latest LTS version
Re: First Custom Drupal Module Using a CiviCRM Hook Works!
March 04, 2010, 11:59:12 pm
Very useful indeed, we will use it for a profile where a person can enter a household, with all the individuals. Once I get to it (probably in about 3 weeks) I will post the result here!
Consultant/project manager at EEatWork and CiviCooP (http://www.civicoop.org/)

FatherShawn

  • Ask me questions
  • ****
  • Posts: 372
  • Karma: 25
    • C3 Design
  • CiviCRM version: 4.2.11
  • CMS version: Drupal 7.23
  • MySQL version: 5.5.32
  • PHP version: 5.3.10
Re: First Custom Drupal Module Using a CiviCRM Hook Works!
March 05, 2010, 03:22:39 am
Quote from: peterd on March 04, 2010, 08:38:26 pm
This sounds like a really useful contribution. If I understand it this code (or at least the hook) means a Profile could be used for someone who is signing up for something (info, event, membership?) and the above could be used to let them add a contact for someone eg child, c-habitant, team mate, so that the other contact is also created and the relationship is created on the fly (with the potential from Eileen's code to then also force permissions etc)

That's right Peter!  In my case an Applicant is creating a Reference.  I was just excited that I wrote custom code after a 22 year break and it worked.  But I can see that the next level of development for this would be to make it generally useful.  The profile and relationship need to be made admin selectable or it's only useful if someone can edit the code.  It feels really good to be able to give back to the community.  8)
Lead Developer, C3 Design.
Twitter: @FatherShawn

Coleman Watts

  • Administrator
  • I’m (like) Lobo ;)
  • *****
  • Posts: 2346
  • Karma: 183
  • CiviCRM version: The Bleeding Edge
  • CMS version: Various
Re: First Custom Drupal Module Using a CiviCRM Hook Works!
April 04, 2010, 08:55:05 pm
Father Shawn, thanks so much for your work on this module. I, too, haven't written any code in years and years, and am just learning PHP. This is an amazing jump-start into doing exactly what I want to do for my school website. When people apply for jobs and internships, they can list their references, and when prospective students apply, they can tell us who their parents are as well as who will be providing letters of recommendation!  One extension I'll need to add to this module is the automatic creation of activities: so that when a person applies online, an "applied online" activity will be created for them.  Another extension would be to automatically send an email to an applicant's references giving them a link to an appropriate webform.  I'll try to work on those myself, but any advice would be welcome!
Try asking your question on the new CiviCRM help site.

xavier

  • Forum Godess / God
  • I’m (like) Lobo ;)
  • *****
  • Posts: 4453
  • Karma: 161
    • Tech To The People
  • CiviCRM version: yes probably
  • CMS version: drupal
Re: First Custom Drupal Module Using a CiviCRM Hook Works!
April 05, 2010, 01:39:26 am
If you plan using civicrm in a school, have a look at the sfschool module

http://svn.civicrm.org/sfschool/trunk/

Quite a few nice features have been implemented and describe by Lobo in the blog.

X+
-Hackathon and data journalism about the European parliament 24-26 jan. Watch out the result

Pages: [1] 2
  • CiviCRM Community Forums (archive) »
  • Old sections (read-only, deprecated) »
  • Developer Discussion »
  • APIs and Hooks (Moderator: Donald Lobo) »
  • First Custom Drupal Module Using a CiviCRM Hook Works!

This forum was archived on 2017-11-26.