I am adding a Soundex featured to the advanced search. I am using the queryObjects hook to add this into the query. The documentation on this is spotty, only referencing CiviHR. I have downloaded that and gone though it, matching my code to it as closely as I can, but I am having issues getting my values to save/bind to the form.
The code adds nicely to the advanced search:
However, I fill out the fields and submit the form, the fields are not populated after the results load. I was able to bind the fields to the form in the postProcess hook (below) so the values are repopulated in the search form, but the query and qill are not affected.
There are a couple of parts to this extension:
Query Objects Hook In my main extension main file
function myextenion_civicrm_queryObjects (&$queryObjects, $type = 'Contact') {
if ($type == 'Contact') {
$queryObjects[] = new CRM_Myextension_BAO_Query_Soundex();
}
}
CRM/Myextension/BAO/Query/Soundex.php
<?php
class CRM_Myextenion_BAO_Query_Soundex extends CRM_Contact_BAO_Query_Interface {
public static $soundex_fields = [
'soundex_first_name' => [
'name' => 'soundex_first_name',
'title' => 'First Name Sounds Like',
'type' => CRM_Utils_Type::T_STRING,
],
'soundex_last_name' => [
'name' => 'soundex_last_name',
'title' => 'Last Name Sounds Like',
'type' => CRM_Utils_Type::T_STRING,
],
];
public function &getFields() {
$return = static::$soundex_fields;
return $return;
}
public function from($name, $mode, $side) {
return '';
}
public function where(&$query) {
if (empty($query->_params)) return;
foreach ($query->_params as $id => $param) {
if (empty($param[0])) {
continue;
}
$this->whereClauseSingle($param, $query);
}
}
public function whereClauseSingle(&$values, &$query) {
list($name, $op, $value, $grouping, $wildcard) = $values;
$fields = $this->getFields();
if (!array_key_exists($name,$fields)) return;
$field = $fields[$name];
$fieldName = substr($field['name'],8); // strip off the soundex_ at the beginning
$query->_qill[$grouping][] = ts($field['title'])." - '$value'";
$query->_where[$grouping][] = CRM_Contact_BAO_Query::buildClause("SOUNDEX(contact_a.".CRM_Core_DAO::escapeString($fieldName).")", "=", soundex($value), "String");
}
public function getPanesMapper(&$panes) {
$panes['Soundex'] = 'civicrm_contact';
}
public function registerAdvancedSearchPane(&$panes) {
$panes['Soundex'] = 'soundex';
}
public function buildAdvancedSearchPaneForm(&$form, $type) {
// echo pre($form->_formValues);
if (in_array($type,[
'soundex',
])) {
$fields = $this->getFields();
foreach ($fields as $name => $label) {
$form->add('text', $name, ts($label['title']));
}
}
}
public function setAdvancedSearchPaneTemplatePath(&$paneTemplatePathArray, $type) {
if (in_array($type,[
'soundex',
])) {
$template = ucfirst($type);
$paneTemplatePathArray[$type] = "CRM/Contact/Form/Search/Criteria/{$template}.tpl";
}
}
}
CRM/Contact/Form/Search/Criteria/Soundex.tpl
<table class="form-layout">
<tr>
<td>
<label>{ts}{$form.soundex_first_name.label}{/ts}</label><br />
{$form.soundex_first_name.html}
</td>
<td>
<label>{ts}{$form.soundex_last_name.label}{/ts}</label><br />
{$form.soundex_last_name.html}
</td>
<td>
{* <label>{ts}Use OR on Soundex (default AND){/ts}</label><br />
{$form.soundex_or_and.html} *}
</td>
</tr>
</table>
Post Process hook (only kinda of working)
function myextension_civicrm_postProcess($formName, &$form) {
switch ($formName) {
case 'CRM_Contact_Form_Search_Basic':
case 'CRM_Contact_Form_Search_Advanced':
// Soundex
if (!empty($_POST)) {
foreach(CRM_Myextension_BAO_Query_Soundex::$soundex_fields as $field => $label) {
$filterVal = CRM_Utils_Request::retrieve($field, 'String', $form);
if (empty($filterVal)) continue;
$form->_formValues[$field] = $filterVal;
}
$form->set('formValues', $form->_formValues);
}
break;
}
}