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 (Moderator: Donald Lobo) »
  • out of memory (on custom 'multiple member' signup form)
Pages: [1]

Author Topic: out of memory (on custom 'multiple member' signup form)  (Read 5406 times)

bob

  • I’m new here
  • *
  • Posts: 6
  • Karma: 0
  • CiviCRM version: 4.2.6
  • CMS version: Wordpress 3.4.2
  • MySQL version: ?
  • PHP version: 5
out of memory (on custom 'multiple member' signup form)
June 12, 2013, 10:24:54 pm
Hello there,
I'm having memory problems with some code I added to my CiviCRM which is installed in Wordpress.

I tried to write some custom code to create a form through which a new member could enter his data and those of his family members all at once when signing up to Civi.
(The organization has a maximum of 4 extra members per each new member, so that's a 4-party family max.) What I need is something like what is discussed here: http://forum.civicrm.org/index.php?topic=9175.0. Or what is described as "Team signup" here: http://civicrm.org/blogs/colemanw/new-possibilities-webform-integration. Or even what's under "Handling multiple contacts and contact types" here: http://civicrm.org/blogs/colemanw/new-possibilities-webform-integration. Since I'm not in Drupal I had to make this happen without 'webforms'.

Here's what I did:
  • created a set of custom fields with name, surname and 7 other fields for each of the 4 extra dependant members — that totals 36 alphanumeric fields in this custom fields set.
  • created a profile for the form, adding those 36 fields manually to the first 17 default fields (used for the main new member, the 'head' of the family).
  • put some code in "civihooks.php" (http://wiki.civicrm.org/confluence/display/CRMDOC42/Hook+Reference) to deal with all the extra fields (BTW, that was how I found out there was a problem with the Wiki documentation on that, and then I fixed it there).

Now this is where the fun begins. My 'hooks' basically does this: in a "wordpress_civicrm_postProcess" it creates each of the new members (at most 4) and then 'connects' every one of them to the main member just created by civi (connecting is comprised of: sharing same address, setting a relationship, copying the telephone from the master to the dependants); all using the "civicrm_api" (calls).

After all this I get this a nice form with lots of fields to be filled:
http://aamac.org.br/associe-se/formulario/?page=CiviCRM&q=civicrm/profile/create&gid=19&reset=1
I fill them all, but when 'submit' is clicked, my problems begin.

The error I usually get when submitting is:
Code: [Select]
Fatal error: Out of memory (allocated 406847488) (tried to allocate 67108939 bytes) in [...]/wp-content/plugins/civicrm/CRM/Core/BAO/UFGroup.php on line 74Now I'm not sure what's causing this and how I could prevent it.

Some questions that occur to me:
What is 'UFGroup.php'? Is there a reason why the error is showing there? Is there a way I can lower memory consumption when creating and 'connecting' the new users? Are the 36 alphanumeric fields 'too much'? Can I somehow calculate what would be the most my server can take? What other tests could I make to find out more stuff? What more information is needed for someone to help me?

Also, maybe there is a more elegant solution than what I'm doing; I'd really appreciate to know that if true.
If needed I can send the code I wrote for the 'hooks', but I'd have to clean it up a bit before (I was planning on putting it up somewhere, but since it doesn't work so well, or at all, I haven't yet ).

Any ideas?

Thanks a lot (a lot!) in advance.
Roberto

lolas

  • I post frequently
  • ***
  • Posts: 134
  • Karma: 9
    • Freeform Solutions
  • CiviCRM version: Several
  • CMS version: Drupal
  • MySQL version: 5.1+
  • PHP version: Several
Re: out of memory (on custom 'multiple member' signup form)
June 13, 2013, 04:28:27 pm
If I read correctly then your code has already allocated about 388MB. Probably near the php memory_limit for your server.

UFGroup.php is part of the profile code and it can usually handle more than 36 fields. I would guess that the error is in your hooks and since it happens on submit then it could be hook_civicrm_postProcess or hook_civicrm_post perhaps? I think if you are still having this problem then you should with reply at least that part of your code for better help.

You might be able to figure out at least which hook is the problem by inserting var_dump(debug_backtrace()); just before line 74 (back up the original file first).
You could also use a custom error handler. A simple example is shown here: http://stackoverflow.com/questions/3224809/is-there-a-php-ini-directive-that-enables-stack-traces-on-errors

Freeform Solutions provides technology and management consulting, website and database development, and managed internet hosting solutions for not-for-profit organizations (NFPs).

bob

  • I’m new here
  • *
  • Posts: 6
  • Karma: 0
  • CiviCRM version: 4.2.6
  • CMS version: Wordpress 3.4.2
  • MySQL version: ?
  • PHP version: 5
Re: out of memory (on custom 'multiple member' signup form)
June 24, 2013, 02:26:16 pm
Hi there,
I've been trying to tidy up the code to post it here.

Before that, I looked into "UFGroup.php" and line 74 is a commented line just before "static function getContactType($id)". I think adding the "var_dump(debug_backtrace());" there wouldn't help. Right?

Now, my code: it is relatively simple, just a "postProcess":
Code: [Select]
function wordpress_civicrm_postProcess($formName, &$form) {

require_once "CRM/Core/Error.php";
require_once 'api/api.php';
require_once 'CRM/Core/BAO/CustomField.php';

$gid=$form->getVar( '_gid' );

// if this is a family form (with the multiple fields we need)
if($gid==19){
    // set name of the group of added vars (customs fields set)
    $groupTitle='Dependentes do Associado Familiar';

    //get master id
    $master_contact_id = $form->getVar( '_id' );

    //get master's address (as 'array')
    $master_address = civicrm_api( 'address', 'getsingle',
    array('version' =>3,
        'options' => array('limit' => 1,
        'sort' => 'is_primary DESC'),
        'contact_id' => $master_contact_id));
         
    //get master residential telephone
    $master_telephone_number = $form->exportValue('phone-Primary-1');

    //how many 'subcontacts' are there? (number of dependants filled in the form)
    $total_sub_contacts = 0;
    for($i = 1; $i <= 4; $i++){
        if( $form->elementExists('custom_' . CRM_Core_BAO_CustomField::getCustomFieldID( 'Nome Familiar '.$i, $groupTitle ))){
            $total_sub_contacts++;
        }else{
            break;
        }
    }

    //all subcontacts data share the same structure:
    $field_initials = array(
            'first_name'=>'Nome',
            'last_name'=>'Sobrenome',
            'email'=>'Email',
            'custom_2'=>'CPF',
            'custom_3'=>'RG',
            'gender'=>'Genero',
            'birth_date'=>'Data de Nascimento',
            'parentesco'=>'Grau de Parentesco',
            'cellphone'=>'Telefone Celular',
        );

    //loop through all possible sub_contacts:
    for ($member_num = 1; $member_num <= $total_sub_contacts; $member_num++) {
        //prepare current subcontact's data:
        $form_values = array();
        foreach ($field_initials as $field_name => $field_initial){
            //check whether field was filled
            if( $form->elementExists('custom_' . CRM_Core_BAO_CustomField::getCustomFieldID( $field_initial." Familiar ".$member_num, $groupTitle ))){
                $form_values[$field_name] = $form->exportValue('custom_' . CRM_Core_BAO_CustomField::getCustomFieldID( $field_initial." Familiar ".$member_num, $groupTitle ));
            }else{
                $form_values[$field_name] = '';
            }
        }

        //creates 'sub_contact' (the dependant)
        $sub_contact_id = create_contact($form_values);
   
        //link sub addresses with master's
        $sub_contact_address = array_merge($master_address,array('contact_id' => $sub_contact_id, 'master_id' => $master_address['id'], 'version' => 3));
        unset ($sub_contact_address['id']);
        $linked_address = civicrm_api('Address','Create',$sub_contact_address);
        if ( civicrm_error ( $linked_address )) { return $linked_address['error_message']; }
   
        //create relationship with master
        create_relationship($master_contact_id,$sub_contact_id,10,'Grau de parentesco do dependente: '.$form_values['parentesco']);
        //create sub's cellular telephone
        create_telephone($sub_contact_id, $form_values['cellphone'], 2, 1);//2: cell; 1:primary        
        //create residential telephone for sub_contact from master's
        create_telephone($sub_contact_id, $master_telephone_number, 1, 0);//1: telefone normal; 0:not primary
    }
}
}

The functions which are called there are declared in "civicrmHooks.php" just before the "wordpress_civicrm_postProcess()" function, they are as follows:
Code: [Select]
function create_contact($form_values){

$contactParams = array(
                    'first_name'    => $form_values['first_name'],
                    'last_name'     => $form_values['last_name'],
                    'email'         => $form_values['email'],
                    'custom_2'     => $form_values['custom_2'], //document 1 (CPF)
                    'custom_3'      => $form_values['custom_3'], //document 2 (RG)
                    'birth_date' => $form_values['birth_date'], //date of birth
                    'gender_id' => $form_values['gender'], //1,2,3 (fem, masc, other)
                    'custom_8' => True,
                    'contact_type'  => 'Individual',
                    'dupe_check'    => True,
                    'version' => 3,
                    );

    $sub_contact = civicrm_api('Contact', 'Create', $contactParams);
    if ( civicrm_error ( $sub_contact )) { return $sub_contact['error_message']; }
   
    return $sub_contact['id'];
}

function create_telephone($contact_id,$phone,$type,$is_primary){
$p_params = array(
  'contact_id' => $contact_id,
  'location_type_id' => 1, //residential phone
  'phone_type_id' => $type, //cellphone
  'phone' => $phone,
  'is_primary' => $is_primary,
  'version' => 3,
);

$phone = civicrm_api( 'phone','create',$p_params );
    if ( civicrm_error ( $phone )) { return $phone['error_message']; }
    unset($p_params);
    unset($phone);
}

function create_relationship($a,$b,$rel_id,$desc){ 
    //create
    $rel_params = array(
  'contact_id_a' => $a,
  'contact_id_b' => $b,
  'relationship_type_id' => $rel_id,
  'is_active' => 1,
  'description' => $desc,
  'version' => 3,
);
$relationship = civicrm_api( 'relationship','create',$rel_params );
    if ( civicrm_error ( $relationship )) { return $relationship['error_message']; }
    unset($relationship);
    unset($rel_params);
}

Hope you (or someone) can spot what is something wrong with those.
Maybe there is a huge memory leak caused by bad use of the api somewhere I can't see... (Or even a basic programming mistake!)

Thanks again

CiviTeacher.com

  • I live on this forum
  • *****
  • Posts: 1282
  • Karma: 118
    • CiviTeacher
  • CiviCRM version: 3.4 - 4.5
  • CMS version: Drupal 6&7, Wordpress
  • MySQL version: 5.1 - 5.5
  • PHP version: 5.2 - 5.4
Re: out of memory (on custom 'multiple member' signup form)
June 25, 2013, 12:42:49 pm
Are you attaching PDFs to your receipts?  If so, try turning off this feature in Administer > System Settings > Logging and reCaptcha page. 

Do a registration, then tell me if you still get the error.
Try CiviTeacher: the online video tutorial CiviCRM learning library.

bob

  • I’m new here
  • *
  • Posts: 6
  • Karma: 0
  • CiviCRM version: 4.2.6
  • CMS version: Wordpress 3.4.2
  • MySQL version: ?
  • PHP version: 5
Re: out of memory (on custom 'multiple member' signup form)
June 26, 2013, 01:10:14 am
No Stoob, that's not it.
"Attach PDF copy to receipts" is set to "No".
Thanks anyway.

Any other ideas?

lolas

  • I post frequently
  • ***
  • Posts: 134
  • Karma: 9
    • Freeform Solutions
  • CiviCRM version: Several
  • CMS version: Drupal
  • MySQL version: 5.1+
  • PHP version: Several
Re: out of memory (on custom 'multiple member' signup form)
July 10, 2013, 08:15:50 am
Sorry for the slow reply. I guess I wasn't subscribed to the thread.

If you are still having this problem perhaps you can give it a try without creating the relationship. If it is a relationship with permissions it may cause a rebuild of the ACL cache.

Also, this is probably not the issue but you can probably reduce the number of function calls in the section where you call this loop by exporting all the form parameters to an array in one go.

Perhaps change this:
Code: [Select]
foreach ($field_initials as $field_name => $field_initial){           
  //check whether field was filled
   if( $form->elementExists('custom_' . CRM_Core_BAO_CustomField::getCustomFieldID( $field_initial." Familiar ".$member_num, $groupTitle ))){
     $form_values[$field_name] = $form->exportValue('custom_' . CRM_Core_BAO_CustomField::getCustomFieldID( $field_initial." Familiar ".$member_num, $groupTitle ));
   }else{
     $form_values[$field_name] = '';
   }
}

to something like:
Code: [Select]
$form_params = $form->exportValues(); or $form_params = $form->_params; // I think this varies depending on which form
foreach ($field_initials as $field_name => $field_initial){ 
  if(isset($form_params['custom_' . CRM_Core_BAO_CustomField::getCustomFieldID( $field_initial." Familiar ".$member_num, $groupTitle )]) {
    etc.
  }
}

If you want to try the var_dump(debug_backtrace()) or dpm(debug_backtrace()) then yes do not put it on a commented line.
Freeform Solutions provides technology and management consulting, website and database development, and managed internet hosting solutions for not-for-profit organizations (NFPs).

bob

  • I’m new here
  • *
  • Posts: 6
  • Karma: 0
  • CiviCRM version: 4.2.6
  • CMS version: Wordpress 3.4.2
  • MySQL version: ?
  • PHP version: 5
Re: out of memory (on custom 'multiple member' signup form)
July 23, 2013, 09:15:43 pm
Hi there lolas and others,
finally I had time to go back to this. And actually find where the problem lies! (I'll post the whole story, for reference)

First of all I have to correct myself (and I suppose this can help solve this whole mystery): unlike I said on my first post, the error is not on line "74", but 774!!! (on civicrm/CRM/Core/BAO/UFGroup.php)

Lolas, out of your suggestions (btw: thanks a lot for them!), I began with the change to the 'foreach'; it ended up like so:
Code: [Select]
$form_params = $form->exportValues(); //the other way you suggested didn't seem to work
foreach ($field_initials as $field_name => $field_initial){ 
$field_internal_name='custom_' . CRM_Core_BAO_CustomField::getCustomFieldID( $field_initial." Familiar ".$member_num, $groupTitle );
if(isset($form_params[$field_internal_name])) {
//store actual value of current field taken from $form in 'form_values'
$form_values[$field_name] = $form_params[$field_internal_name];
}
}
After this I tested it and, I still had the memory overflow!... (Still I left this bit of code like you suggested, much more elegant!)

Next, I tried using the dpm() thing, but it apparently does not exist:
Code: [Select]
Fatal error:  Call to undefined function dpm() in .../wp-content/plugins/civicrm/civicrm/CRM/Core/BAO/UFGroup.php on line 775
Then I proceeded to "var_dump(debug_backtrace());", which didn't help much, since after I added it there were no more errors. I was just being thrown at the Wordpress page which holds the form; not even the memory bug error wasn't being shown anymore... I suppose it has to do with how the info is 'echoed' back into that page. Either way, what I did was add a call to the unknown 'dpm()' function, right after the call to the var_dump, and it worked. Now it really gets weirder: my browser almost crashed and I got no less than 100,000 lines of backtrace (that's right: more than a hundred thousand!). Needless to say, I can't even start making sense of all these lines. I'm not even sure if this is the backtrace that I should be looking at (I found none of the variables I declared in my 'civicrmHooks.php', for example). The backtrace is so big in fact that I could not even paste it here.

Then, I tried going back to Stoob's suggestion in a different way, I just removed the email which was set to be notified when the form was filled (in Admin->Profiles->[profile]->Settings->Advanced Settings->Notify when the form is submitted). And then, finally, it WORKED!  :D

Since I really need an email to be sent when this form is filled, the question is: how should I do it? (I'm obviously assuming that the whole problem was indeed with the email sending.) It doesn't have to have all the info from the form (which, I suppose, was what was causing the memory overflow — all those form fields were probably just too much information to send via email). A message with a simple link to the newly created 'master' profile would be just fine.

Apparently there is a way to create and send an email from inside 'civicrmHooks' (as per this http://forum.civicrm.org/index.php?topic=28042.0 unfortunately there is no API at the moment).

I used "CRM_Utils_Mail::send", it ended up like so:
Code: [Select]
require_once 'CRM/Core/BAO/Domain.php';
require_once "CRM/Utils/Mail.php";

// send an email to the administrator notifying the new association
$params = array( );

//get default 'from' email address.
$name_and_email = CRM_Core_BAO_Domain::getNameAndEmail();
$from_name = $name_and_email[0];
$from_email = $name_and_email[1];

if ( isset($from_email) && isset($from_name)) {

    $params['from'] = '"' . $from_name . '" <' . $from_email. '>';
    // since the message is being sent 'to' and 'from' the admin, we do:
    $params['toEmail'] = $from_email;
    $params['toName'] = $from_name;
    //message title:
    $params['subject'] = "New Family ".$form_params['first_name']." ".$form_params['last_name'];
    $objectValues = $form_params['first_name']." ".$form_params['last_name'].": ________/wp-admin/admin.php?page=CiviCRM&q=civicrm/contact/view&action=view&reset=1&cid=".$master_contact_id;   
    $params['text'] = "
Message...
Link to new 'head' member:
$objectValues

Thank you note, etc
";
    //now just send the message!
    CRM_Utils_Mail::send( $params );
}

What do you think? Is there a better way? Or even a way of fixing the error itself (the memory overflow caused by Civi's own email sending)?

Thanks again to all of you for the help!

lolas

  • I post frequently
  • ***
  • Posts: 134
  • Karma: 9
    • Freeform Solutions
  • CiviCRM version: Several
  • CMS version: Drupal
  • MySQL version: 5.1+
  • PHP version: Several
Re: out of memory (on custom 'multiple member' signup form)
July 24, 2013, 05:46:19 am
HI,

I forgot you said you were on Wordpress. Sorry for suggesting dpm() then - it is a Drupal function and requires the devel module. It looks like the Wordpress equivalent is something like this: http://wordpress.org/plugins/debug-bar/.

I'm pretty sure that if you got more than 100,00 lines of backtrace then either huge pieces of data are being passed as arguments or there is a runaway loop somewhere in the code. The functions should not be nested that deep. Still if troubleshooting the email sending gets it working then I'm surprised but that's good!

Can you send an email to that address from the contact page?  (Create a contact for them if there isn't one.)
Freeform Solutions provides technology and management consulting, website and database development, and managed internet hosting solutions for not-for-profit organizations (NFPs).

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: out of memory (on custom 'multiple member' signup form)
July 24, 2013, 01:55:39 pm

can u post the diff between your modified CRM/Utils/Mail.php

easier for us to see the changes

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

Pages: [1]
  • CiviCRM Community Forums (archive) »
  • Old sections (read-only, deprecated) »
  • Developer Discussion (Moderator: Donald Lobo) »
  • out of memory (on custom 'multiple member' signup form)

This forum was archived on 2017-11-26.