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) »
  • Support »
  • Using CiviCRM »
  • Using Core CiviCRM Functions (Moderator: Yashodha Chaku) »
  • Writing a timestamp into a custom data field
Pages: [1]

Author Topic: Writing a timestamp into a custom data field  (Read 3564 times)

ThePayIsLousy

  • Guest
Writing a timestamp into a custom data field
August 14, 2009, 10:08:56 am
I'll ask my question first, and will then explain why (in case I'm being stupid and am asking the wrong question).  I did do some forum searching first...

Is there a way to make clicking the SAVE button write a timestamp to a custom data field?

Why: I have a profile set up to collect info for a printed telephone directory.  The problem is that the person who creates the directory will be frequently importing CiviCRM data into a master spreadsheet that includes data from other sources.  She doesn't want to wait until all of the CiviCRM data is collected and handed off to her -- she wants to divide-and-conquer and xfer the data in batches. 

I either need to lock users out of changing their data once they have entered it (requiring some kind of manual change process), or store modification date/time so that the exported spreadsheet can be sorted.

I did some nosing around here, but I'm not sure I'm on the right track.
http://wiki.civicrm.org/confluence/display/CRMDOC/CiviCRM+hook+specification#CiviCRMhookspecification-hookcivicrmpostProcess
I know I won't get much further w/o some guidance, though.  Suggestions appreciated -- and I promise to post my completed solution so that others can benefit. 

Thank you!

      Mike

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: Writing a timestamp into a custom data field
August 14, 2009, 10:26:15 am

1. create a custom field of data type date and html type date. Enable the "View Only" flag

2. use the postProcess hook below to update the timestamp as needed

if u need help, ping us on IRC

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

ThePayIsLousy

  • Guest
Re: Writing a timestamp into a custom data field
August 14, 2009, 12:10:19 pm
Quote from: Donald Lobo on August 14, 2009, 10:26:15 am
2. use the postProcess hook below to update the timestamp as needed

Thanks, lobo!  When you say "postProcess hook below", did you mean to include something else -- or were you referring to the link I posted above?

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: Writing a timestamp into a custom data field
August 14, 2009, 12:34:32 pm

the link above. There is also a sample module in the distribution: civitest.module.sample

You can also check out a more detailed example at:

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

A writeup on that module is here: http://civicrm.org/node/618

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

ThePayIsLousy

  • Guest
Re: Writing a timestamp into a custom data field
August 16, 2009, 06:42:34 am
lobo and all,

What I seem to have the most trouble with re: CiviCRM is that I can only find 30,000 foot views and the most detailed of details.  I never seem to be able to find a cookbook recipe that goes from the 30,000 foot view all the way down to the details.  So, what I have done is set up Drupal and CiviCRM from scratch and kept a complete journal of every necessary step to get from nothing to where I am.  I'm hopeful that other CiviCRM newbies will find it useful, and I'll be posting it shortly on the documentation section of the forum.

Back to this topic.  lobo posted some *very* helpful info, but I can't quite figure out how to implement the structure that accomplishes the integration w/ my existing system.  After reading dozens (many dozens) of forum posts and documents, I think I have a general idea of what I need to do.  Would lobo or someone else please help me fill in the blanks?  I also installed mIRC if that is the preferred way to get help for this (I've never used IRC before, despite having been a programmer since 1978)...

--Create .info and .module files for my hooks module.  Where do they go?  drupalroot/sites/all/modules/civicrm/drupal/modules?

--I picked a short descriptive name like lobo's sfschool.  But, to borrow a punchline from an old joke about a Thermos' ability to keep hot things hot and cold things cold, how do CiviCRM know?  How will my installation of CiviCRM know to call, e.g., sfschool_civicrm_postProcess when my user clicks the SAVE button on a form?  [Update: OK, I think I understand -- Drupal/CiviCRM will automagically look for and call all *civicrm_postProcess routines in all modules stored in the modules directory.]

--Following lobo's example and using a tip from Dave Greenberg to get my custom field # from viewing the page source, I gather that I want to use sfschool_civicrm_postProcess to call sfschool_civicrm_postProcess_CRM_Profile_Form_Edit_3 to act on profile #3 field custom_47[M] and store the current timestamp. If that's right, can anyone give me the actual code to store the timestamp or point me to an example?  The only timestamp examples I could find are filling in a default value before initial form display -- I'm going the other way (i.e. before saving to the db).

--I need to enable the module in Drupal's control panel.  I'm pretty sure I can do that step!

I hate bothering people.  Again, I promise to give back by documenting the entire process and then supporting any newer newbies who read my instructions in the future.  But, in the mean time, I'm kinda stuck -- I know this is a fairly simple change, but it requires a lot of understanding re: the details of Drupal, CiviCRM and perhaps mySQL that I just don't yet have.  Thanks!!
« Last Edit: August 16, 2009, 01:12:33 pm by Mike Stein »

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: Writing a timestamp into a custom data field
August 16, 2009, 03:34:02 pm

hey mike

thanx for keeping notes :)

1. to respond to your specific question: Drupal does the magic and loads all the modules that are enabled and active as you discovered. In joomla and standalone we follow a specific convention (i.e. file should be called civicrmHooks.php in the main civicrm directory and functions should be called joomla_civicrm_postProcess etc)

2. Check the sfschool code, specifically Utils/ExtendedCare.php. I do store a timestamp in the db there (search for start_date_7, line 354 right now, but will change since i'm adding more code etc). Doing it that way, minimizes the chances of sql injection. The exact code is:

Code: [Select]
INSERT INTO civicrm_value_extended_care_2                                                                                                                         
( entity_id, term_4, name_3, description_9, instructor_5, day_of_week_10, session_11, fee_block_6, start_date_7, end_date_8, has_cancelled_12 )                   
VALUES                                                                                                                                                           
( %1, %2, %3, %4, %5, %6, %7, %8, %9, %10, 0 )                                                                                                                   
";

            $params = array( 1  => array( $childID, 'Integer' ),
                             2  => array( $classValues['term'], 'String' ),
                             3  => array( $classValues['name'], 'String' ),
                             4  => array( CRM_Utils_Array::value( 'description', $classValues, '' ),
                                         'String' ),
                             5  => array( CRM_Utils_Array::value( 'instructor', $classValues, '' ),
                                          'String' ),
                             6  => array( $classValues['day'], 'String' ),
                             7  => array( $classValues['session'], 'String' ),
                             8  => array( $classValues['fee block'], 'Float' ),
                             9  => array( CRM_Utils_Date::getToday( null, 'YmdHis' ), 'Timestamp' ),
                             10 => array( CRM_Utils_Date::isoToMysql( $classValues['end date'] ),
                                          'Timestamp' ) );
        CRM_Core_DAO::executeQuery( $query, $params );

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

ThePayIsLousy

  • Guest
Re: Writing a timestamp into a custom data field
August 16, 2009, 07:37:18 pm
Thanks, lobo!

OK, let's see if a guy who doesn't know php or sql can hack CiviCRM using hooks...  :-)

Is this the code to write a timestamp into field #47 when a user clicks "SAVE"?  Here is my .MODULE code:

Code: [Select]
<?php

function drupalptsav2_help( ) {
    switch (
$section) { 
    case 
'admin/modules#description': 
        return 
t('Implements hooks for CiviCRM to customize the PTSA site');
    default :
        return;
    } 
}


function 
drupalptsav2_civicrm_postProcess( $formName, &$form ) {
    if ( 
is_a( $form, 'CRM_Profile_Form_Edit' ) ) {
        
$gid = $form->getVar( '_gid' );
        if ( 
$gid == 3 ) {
            
drupalptsav2_civicrm_postProcess_CRM_Profile_Form_Edit_3( $formName, $form, $gid );
            return;
        }
    }
}


function 
drupalptsav2_civicrm_postProcess_CRM_Profile_Form_Edit_3( $formName, &$form, $gid ) {

// *****is this how to get the proper entity_id?*****
    
$userID   = $form->getVar( '_id' );

// ***** Is this how to insert the timestamp into field #47, my last modified field? *****
    
$query = "
INSERT INTO civicrm_value_directory_info_fields_2
( entity_id,  last_modified_47 )
VALUES
( %1, %2)
"
;
            
    
$params = array( 1  => array( $userID, 'Integer' ),
                             
2  => array( CRM_Utils_Date::getToday( null, 'YmdHis' ), 'Timestamp' ));
    
CRM_Core_DAO::executeQuery( $query, $params );
}

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: Writing a timestamp into a custom data field
August 16, 2009, 08:59:28 pm

looks good :) did u try running it?

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

ThePayIsLousy

  • Guest
Re: Writing a timestamp into a custom data field
August 17, 2009, 05:42:57 am
Quote from: Donald Lobo on August 16, 2009, 08:59:28 pm
looks good :) did u try running it?
W/o your blessing?  R u crazy?  :)

OK, I tried it!  Didn't work, but I gather it's b/c I shouldn't be using the sql INSERT statement?  Am I looking for REPLACE?   And, if so, can I just write one field (in this case "Last modified"), or do I need to first read in all of the columns so that I can rewrite them all into a new replacement record?  I spent some time in the mySQL docs, but I think I need to spend some more time...

Code: [Select]
Error Details:

Array
(
    [callback] => Array
        (
            [0] => CRM_Core_Error
            [1] => handle
        )

    [code] => -5
    [message] => DB Error: already exists
    [mode] => 16
    [debug_info] =>
INSERT INTO civicrm_value_directory_info_fields_2
( entity_id,  last_modified_47 )
VALUES
( 1, 20090817052618)
 [nativecode=1062 ** Duplicate entry '1' for key 2]
    [type] => DB_Error
    [user_info] =>
INSERT INTO civicrm_value_directory_info_fields_2
( entity_id,  last_modified_47 )
VALUES
( 1, 20090817052618)
 [nativecode=1062 ** Duplicate entry '1' for key 2]
    [to_string] => [db_error: message="DB Error: already exists" code=-5 mode=callback callback=CRM_Core_Error::handle prefix="" info="
INSERT INTO civicrm_value_directory_info_fields_2
( entity_id,  last_modified_47 )
VALUES
( 1, 20090817052618)
 [nativecode=1062 ** Duplicate entry '1' for key 2]"]
)


Code: [Select]
<?php

// drupalptsav2.module
// Stored last modified timestamp when user clicks SAVE button on a profile form.
// Modified:
// Created:  090816, Mike Stein


// General instructions for customizing this for your needs; see comments in code
// for specifics.
// --Select a name to replace drupalptsav2.
// --Create <your module name>.info and .module files, and store them in
//    <your drupal root>/sites/all/modules/civicrm/drupal/modules.  Once you
//    enable module in Drupal's Administer panel, Drupal will automagically
//    load them and civiCRM will call any hooks that have the proper suffix
//    (e.g. xxxxxxx_civicrm_postProcess).
//  --Follow the specific instructions in the code below.


function drupalptsav2_help( ) {
    switch (
$section) { 
    case 
'admin/modules#description': 
//      Put your module info here
        
return t('Implements hooks for CiviCRM to customize the PTSA site');
    default :
        return;
    } 
}


function 
drupalptsav2_civicrm_postProcess( $formName, &$form ) {
    if ( 
is_a( $form, 'CRM_Profile_Form_Edit' ) ) {
        
$gid = $form->getVar( '_gid' );
//      Get your profile id from Administer CiviCRM >> Profile; mine is 3
        
if ( $gid == 3 ) {
//          Need your profile # in the call to the edit routine, too!
            
drupalptsav2_civicrm_postProcess_CRM_Profile_Form_Edit_3( $formName, $form, $gid );
            return;
        }
    }
}


function 
drupalptsav2_civicrm_postProcess_CRM_Profile_Form_Edit_3( $formName, &$form, $gid ) {

    
$userID   = $form->getVar( '_id' );

//  directory_info_fields_2 is the actual name of the sql record that holds my profile form
//  info.  Go into phpMyAdmin or however you browse your sql database to get the name
//  (look at the civicrm_value schema).
//  You can do the same thing to get the field name (mine is last_modified_47).  If you
//  multiple fields named something similar, you can determine which field your looking 
//  for by viewing the source code of the Web page that displays your form. 
    
$query = "
INSERT INTO civicrm_value_directory_info_fields_2
( entity_id,  last_modified_47 )
VALUES
( %1, %2)
"
;
            
    
$params = array( 1  => array( $userID, 'Integer' ),
                             
2  => array( CRM_Utils_Date::getToday( null, 'YmdHis' ), 'Timestamp' ));
    
CRM_Core_DAO::executeQuery( $query, $params );
}
[/code]

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: Writing a timestamp into a custom data field
August 17, 2009, 05:51:08 am

yeah, change the INSERT to REPLACE INTO. It will use the entity_id key to either INSERT or UPDATE

i used INSERT since my custom group was a multiple record custom group and i wanted new records created (there is other logic to set end dates for deletions etc in the code)

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

ThePayIsLousy

  • Guest
Re: Writing a timestamp into a custom data field
August 17, 2009, 07:10:50 am
Progress w/ REPLACE!  I now have a timestamp -- but the rest of the data in my profile form data was whacked.  After doing some research, I think maybe I'm looking to use the UPDATE command instead of REPLACE?  What do you think of this (trying not to be a lazy slug and letting you do all of the work)?

I tested it, and it seemed to work (but I'm still scared that I did something wrong and I'll lose data when this goes live).  I don't think I'm ready to put php and sql onto my resume yet...  :)

Code: [Select]
function drupalptsav2_civicrm_postProcess_CRM_Profile_Form_Edit_3( $formName, &$form, $gid ) {

    $userID   = $form->getVar( '_id' );

    $query = "
UPDATE civicrm_value_directory_info_fields_2
SET last_modified_47 = %1
WHERE entity_id = %2
";
           
    $params = array( 1  => array( CRM_Utils_Date::getToday( null, 'YmdHis' ), 'Timestamp' ),
                  2  => array( $userID, 'Integer' ));
    CRM_Core_DAO::executeQuery( $query, $params );
}

ThePayIsLousy

  • Guest
Re: Writing a timestamp into a custom data field
August 22, 2009, 01:19:20 pm
Everything seems to be working -- I have a last modified date on two forms!  Here is a step-by-step HowTo, and the working code:
http://wiki.civicrm.org/confluence/display/CRMDOC/CiviCRM+hook+specification
[Intro section at top for an overview of module writing; last modified date code under postProcess hook section.]

Thanks for the advice along the way, lobo!

Pages: [1]
  • CiviCRM Community Forums (archive) »
  • Old sections (read-only, deprecated) »
  • Support »
  • Using CiviCRM »
  • Using Core CiviCRM Functions (Moderator: Yashodha Chaku) »
  • Writing a timestamp into a custom data field

This forum was archived on 2017-11-26.