CiviCRM/debugging: Difference between revisions

No edit summary
m Text replacement - "<(\/?)source" to "<$1syntaxhighlight"
Tags: Mobile edit Mobile web edit
 
(One intermediate revision by one other user not shown)
Line 1: Line 1:
== Examples ==
Just looking for Fatal errors in the log can help you figure out what's wrong.
<syntaxhighlight lang="bash">
find /var/www/html/ -regex .*log$ -ls
grep Fatal -A3 /var/www/html/wp-content/uploads/civicrm/ConfigAndLog/CiviCRM.ae1lp|tree|search|stat|r.log | grep --color '\[message\]' -B2
</syntaxhighlight>
== Debugging CiviCRM on Drupal using NetBeans and XDebug ==
This article is a detailed walkthrough of debugging CiviCRM on Drupal (using NetBeans and XDebug). We're specifically debugging the behavior of token replacement and UI representation in the CiviMail component.  We've found that if you create 'multi record' custom data that the tokens are not replaced.  We're trying to fix that but we're not sure by just reading the code where the problem lies.  Hopefully the debugger will provide enough inspection capability to see exactly what's going on; and by extension, what's going wrong.  Still haven't found the fix, but it looks like the data (that's there) isn't being picked up in $mailer->compose ([https://github.com/civicrm/civicrm-core/commits/master/api/v3/Mailing.php source])
This article is a detailed walkthrough of debugging CiviCRM on Drupal (using NetBeans and XDebug). We're specifically debugging the behavior of token replacement and UI representation in the CiviMail component.  We've found that if you create 'multi record' custom data that the tokens are not replaced.  We're trying to fix that but we're not sure by just reading the code where the problem lies.  Hopefully the debugger will provide enough inspection capability to see exactly what's going on; and by extension, what's going wrong.  Still haven't found the fix, but it looks like the data (that's there) isn't being picked up in $mailer->compose ([https://github.com/civicrm/civicrm-core/commits/master/api/v3/Mailing.php source])


Line 22: Line 31:
|text=Pro tip: You can Ctrl+click on all the line items in the Call Stack window of NetBeans.  Then press Ctrl+C to copy the text, and paste it into your doc}}
|text=Pro tip: You can Ctrl+click on all the line items in the Call Stack window of NetBeans.  Then press Ctrl+C to copy the text, and paste it into your doc}}


Clicking the "Preview as HTML" button from the compose screen of a draft mailing has a call stack like the following.  Note that a breakpoint is set at '''line 536''' where <source lang=php inline>$details = CRM_Utils_Token::getTokenDetails($mailingParams, $returnProperties, TRUE, TRUE, NULL, $mailing->getFlattenedTokens());</source>
Clicking the "Preview as HTML" button from the compose screen of a draft mailing has a call stack like the following.  Note that a breakpoint is set at '''line 536''' where <syntaxhighlight lang=php inline>$details = CRM_Utils_Token::getTokenDetails($mailingParams, $returnProperties, TRUE, TRUE, NULL, $mailing->getFlattenedTokens());</syntaxhighlight>
<pre>
<pre>
sites/all/modules/contrib/civicrm/api/v3/Mailing.php.civicrm_api3_mailing_preview:536
sites/all/modules/contrib/civicrm/api/v3/Mailing.php.civicrm_api3_mailing_preview:536
Line 97: Line 106:




on line 524 of <code>civicrm/api/V3/Mailing.php</code>, in <source lang="php" inline>civicrm_api3_mailing_preview($params) </source> there is a call to <source lang=php inline>CRM_Mailing_BAO_Mailing::tokenReplace($mailing);</source>
on line 524 of <code>civicrm/api/V3/Mailing.php</code>, in <syntaxhighlight lang="php" inline>civicrm_api3_mailing_preview($params) </syntaxhighlight> there is a call to <syntaxhighlight lang=php inline>CRM_Mailing_BAO_Mailing::tokenReplace($mailing);</syntaxhighlight>


The $mailing is an array with 9 elements, all 'private'
The $mailing is an array with 9 elements, all 'private'
Line 112: Line 121:
loadClass() ends up loading $file CRM/Utils/Token.php (when $class="CRM_Utils_Token")
loadClass() ends up loading $file CRM/Utils/Token.php (when $class="CRM_Utils_Token")


getTokens($string) is called and returns things like <source lang=php>$tokens['general'][] = "wUrl"</source>
getTokens($string) is called and returns things like <syntaxhighlight lang=php>$tokens['general'][] = "wUrl"</syntaxhighlight>


gets passed to _getTokens($prop) and $newTokens is the same as $tokens
gets passed to _getTokens($prop) and $newTokens is the same as $tokens
Line 143: Line 152:
When I click "Preview as HTML", the value is correctly displayed for the first contact in my "Recipient list".  The token is {contact.custom_71}
When I click "Preview as HTML", the value is correctly displayed for the first contact in my "Recipient list".  The token is {contact.custom_71}


I used a breakpoint in <code>civicrm/api/V3/Mailing.php</code> at '''line 536''' where $details gets populated from a call to <source lang=php inline>CRM_Utils_Token::getTokenDetails($mailingParams, $returnProperties, TRUE, TRUE, NULL, $mailing->getFlattenedTokens())</source>
I used a breakpoint in <code>civicrm/api/V3/Mailing.php</code> at '''line 536''' where $details gets populated from a call to <syntaxhighlight lang=php inline>CRM_Utils_Token::getTokenDetails($mailingParams, $returnProperties, TRUE, TRUE, NULL, $mailing->getFlattenedTokens())</syntaxhighlight>


$this is a CRM_Mailing_BAO object. $this->tokens is an array[3] with keys html, text, subject
$this is a CRM_Mailing_BAO object. $this->tokens is an array[3] with keys html, text, subject
Line 198: Line 207:
some of the queries issued:
some of the queries issued:


<source lang="sql">
<syntaxhighlight lang="sql">
SELECT *,  config_backend, locales, locale_custom_strings  FROM civicrm_domain WHERE ( civicrm_domain.id = 1 );
SELECT *,  config_backend, locales, locale_custom_strings  FROM civicrm_domain WHERE ( civicrm_domain.id = 1 );
SELECT subtype.*, parent.name as parent, parent.label as parent_label FROM  civicrm_contact_type subtype INNER JOIN civicrm_contact_type parent ON subtype.parent_id = parent.id WHERE  subtype.name IS NOT NULL AND subtype.parent_id IS NOT NULL  AND subtype.is_active = 1 AND parent.is_active = 1 ORDER BY parent.id;
SELECT subtype.*, parent.name as parent, parent.label as parent_label FROM  civicrm_contact_type subtype INNER JOIN civicrm_contact_type parent ON subtype.parent_id = parent.id WHERE  subtype.name IS NOT NULL AND subtype.parent_id IS NOT NULL  AND subtype.is_active = 1 AND parent.is_active = 1 ORDER BY parent.id;
Line 204: Line 213:
SELECT * FROM civicrm_mailing WHERE ( civicrm_mailing.id = 17 );
SELECT * FROM civicrm_mailing WHERE ( civicrm_mailing.id = 17 );
SELECT * FROM civicrm_domain WHERE ( civicrm_domain.id = 1 );
SELECT * FROM civicrm_domain WHERE ( civicrm_domain.id = 1 );
</source>
</syntaxhighlight>


{{highlight |text=When stepping through lines of code in NetBeans with the XDebug debugger running, you can mouse over a variable and a tooltip will display it's current value.}}
{{highlight |text=When stepping through lines of code in NetBeans with the XDebug debugger running, you can mouse over a variable and a tooltip will display it's current value.}}
Line 267: Line 276:
CRM_Utils_Hook_DrupalBase::CRM_Utils_Hook->invoke() is called which builds the module list and runs the hooks.
CRM_Utils_Hook_DrupalBase::CRM_Utils_Hook->invoke() is called which builds the module list and runs the hooks.


Then runHooks() in <code>CRM/Utils/Hook.php</code> is called; and it's called with <source lang=php>$civiModules, $fnSuffix, $numParams, &$arg1, &$arg2, &$arg3, &$arg4, &$arg5, &$arg6</source>
Then runHooks() in <code>CRM/Utils/Hook.php</code> is called; and it's called with <syntaxhighlight lang=php>$civiModules, $fnSuffix, $numParams, &$arg1, &$arg2, &$arg3, &$arg4, &$arg5, &$arg6</syntaxhighlight>


where
where
Line 287: Line 296:
== AJAX ==
== AJAX ==
The form action is handled by AJAX, and we can see in the $_POST ['entity'] = "Mailing", ['action'] = "create", and ['json'] =  
The form action is handled by AJAX, and we can see in the $_POST ['entity'] = "Mailing", ['action'] = "create", and ['json'] =  
<source lang=javascript wrap>
<syntaxhighlight lang=javascript wrap>
"{"id":"17","domain_id":"1","footer_id":"2","reply_id":"8","unsubscribe_id":"5","resubscribe_id":"6","optout_id":"7","name":"Test of Custom Data","mailing_type":"standalone","from_name":"Greg Rundlett","from_email":"greg@eQuality-tech.com","replyto_email":"greg@eQuality-tech.com","subject":"test","body_html":"<p>Hi {contact.first_name}<br />\nwUrl data is stored as custom 40<br />\nbut the token in the UI is {general.wUrl}<br />\ncustom_40 {custom_40}<br />\ncontact.custom_40 {contact.custom_40}<br />\ngeneral.custom_40 {general.custom_40}<br />\ngeneral.general.custom_40 {general.general.custom_40}</p>\n\n<p>This is the &quot;dufus&quot; {contact.custom_71}</p>\n\n<p>More tests<br />\n{general.articlepath}<br />\n{general.base}<br />\n{general.favicon}<br />\n{general.logo}<br />\n{general.generator}<br />\n{stats.activeusers}<br />\n{stats.admins}<br />\n{stats.images}<br />\n{stats.pages}</p>\n\n<p></p>\n\n<p>And finally, the Bar test of multiple records</p>\n\n<p>\n{contact.custom_72}<br />\n{custom_72}</p>\n","url_tracking":"1","forward_replies":"0","auto_responder":"0","open_tracking":"1","override_verp":"1","created_id":"2","created_date":"2015-10-06 15:49:42","is_archived":"0","visibility":"Public Pages","dedupe_email":"1","hash":"0e95338dfdcbcc5c","email_selection_method":"automatic","is_error":0,"jobs":{},"scheduled_date":null,"groups":{"include":[17],"exclude":[],"base":[]},"mailings":{"include":[],"exclude":[]},"options":{"force_rollback":1},"api.Mailing.preview":{"id":"$value.id"}}"
"{"id":"17","domain_id":"1","footer_id":"2","reply_id":"8","unsubscribe_id":"5","resubscribe_id":"6","optout_id":"7","name":"Test of Custom Data","mailing_type":"standalone","from_name":"Greg Rundlett","from_email":"greg@eQuality-tech.com","replyto_email":"greg@eQuality-tech.com","subject":"test","body_html":"<p>Hi {contact.first_name}<br />\nwUrl data is stored as custom 40<br />\nbut the token in the UI is {general.wUrl}<br />\ncustom_40 {custom_40}<br />\ncontact.custom_40 {contact.custom_40}<br />\ngeneral.custom_40 {general.custom_40}<br />\ngeneral.general.custom_40 {general.general.custom_40}</p>\n\n<p>This is the &quot;dufus&quot; {contact.custom_71}</p>\n\n<p>More tests<br />\n{general.articlepath}<br />\n{general.base}<br />\n{general.favicon}<br />\n{general.logo}<br />\n{general.generator}<br />\n{stats.activeusers}<br />\n{stats.admins}<br />\n{stats.images}<br />\n{stats.pages}</p>\n\n<p></p>\n\n<p>And finally, the Bar test of multiple records</p>\n\n<p>\n{contact.custom_72}<br />\n{custom_72}</p>\n","url_tracking":"1","forward_replies":"0","auto_responder":"0","open_tracking":"1","override_verp":"1","created_id":"2","created_date":"2015-10-06 15:49:42","is_archived":"0","visibility":"Public Pages","dedupe_email":"1","hash":"0e95338dfdcbcc5c","email_selection_method":"automatic","is_error":0,"jobs":{},"scheduled_date":null,"groups":{"include":[17],"exclude":[],"base":[]},"mailings":{"include":[],"exclude":[]},"options":{"force_rollback":1},"api.Mailing.preview":{"id":"$value.id"}}"
</source>
</syntaxhighlight>


== CRM_Utils_Array ==
== CRM_Utils_Array ==