|
Building a Custom Search in CiviCRM
Design your search.
<joomla root>/administrator/components/com_civicrm/civicrm/CRM/Contact/Form/Search/Custom
class CRM_Contact_Form_Search_Custom_employerListing
implements CRM_Contact_Form_Search_Interface {
Register your custom search component
* You will need to insert a record in civicrm_option_value to register your new search. The registration record includes an integer "value" - which is the invoke ID for the search component, the class path (defined in previous step), and the file name.
SELECT * FROM `civicrm_option_value` WHERE option_group_id = ( SELECT id FROM civicrm_option_group WHERE name = 'custom_search' ) In my database, the highest "value" row was 5. So I'll use 6 as the `value` for our new search. Remember this value as we will use it in the URL to view the search form later. The class path is the `label`. The file path and name is the `name`. So, for our Employee Listing example - the insert query is: SELECT @og_id := id FROM civicrm_option_group WHERE domain_id = 1 AND name = 'custom_search'; INSERT INTO civicrm_option_value (option_group_id, value, label, name) VALUES (@og_id, 6, 'CRM_Contact_Form_Search_Custom_EmployerListing', 'CRM/Contact/Form/Search/Custom/EmployerListing.php'); Modify functions in the new custom search file to meet your design.Define result set columns.
/** * Define the columns for search result rows */ $this->_columns = array( ts('Contact Id') => 'contact_id', ts('Individual Name') => 'sort_name' , ts('Individual State') => 'indState' , ts('Employer') => 'employer' , ts('Employer State') => 'empState' ); Create search form fields.
/**
* Define the search form fields here
*/
$form->add( 'text',
'sort_name',
ts( 'Individual\'s Name (last, first)' ) );
\\
$stateProvince = array('' => ts('- any state/province -')) + CRM_Core_PseudoConstant::stateProvince( );
$form->addElement('select', 'state_province_id', ts('Individual\'s State'), $stateProvince);
\\
/**
* If you are using the sample template, this array tells the template fields to render
* for the search form.
*/
$form->assign( 'elements', array( 'sort_name', 'state_province_id') );
* If you want defaults for any form values - create a setDefaultValues() function and define them there. // Setting default search state to California function setDefaultValues( ) { return array( 'state_province_id' => 1004, ); } Define SELECT clause and DEFAULT SORT in the all() function.
// SELECT clause must include contact_id as an alias for civicrm_contact.id
$select = "
distinct(cInd.id) as contact_id,
cInd.sort_name as sort_name,
cEmp.sort_name as employer,
state_province.name as empState
";
Define a default sort - we'll use sort_name asc. if ( ! empty( $sort ) ) { ... } else { $sql .= "ORDER BY sort_name asc"; } ... If you want to modify the value returned in a cell...
// This trivial example appends ' (altered )' to the sort name in each row
function alterRow( &$row ) {
$row['sort_name'] .= ' ( altered )';
}
Define FROM clause.
function from( ) {
return "
civicrm_relationship cR,
civicrm_contact cInd
LEFT JOIN civicrm_address indAddress ON ( indAddress.contact_id = cInd.id AND
indAddress.is_primary = 1 )
LEFT JOIN civicrm_state_province indSP ON indSP.id = indAddress.state_province_id,
civicrm_contact cEmp
LEFT JOIN civicrm_address empAddress ON ( empAddress.contact_id = cEmp.id AND
empAddress.is_primary = 1 )
LEFT JOIN civicrm_state_province empSP ON empSP.id = empAddress.state_province_id
";
}
Define WHERE clause.
function where( $includeContactIDs = false ) { $clauses = array( ); \\ // These are required filters for our query. $clauses[] = "cInd.contact_type = 'Individual'"; $clauses[] = "cR.relationship_type_id = 4"; $clauses[] = "cR.contact_id_a = cInd.id"; $clauses[] = "cR.contact_id_b = cEmp.id"; $clauses[] = "cR.is_active = 1"; \\ // These are conditional filters based on user input $name = CRM_Utils_Array::value( 'sort_name', $this->_formValues ); if ( $name != null ) { if ( strpos( $name, '%' ) === false ) { $name = "%{$name}%"; } $clauses[] = "cInd.sort_name LIKE '$name'"; } \\ $state = CRM_Utils_Array::value( 'state_province_id', $this->_formValues ); if ( $state ) { $clauses[] = "indSP.id = $state"; } ... Define HAVING clause.
Decide on page layout.You can stick with the standard sample template to layout your search form and results (CRM/Contact/Form/Search/Custom/Sample.tpl), or create your own. The sample template simply loops through the list of fields you've defined in the 'elements' array above, and arranges them in a table - one field per row. If you want to lay out the form differently, and/or add styling, custom javascript etc. - create and modify a copy of that file. Then update the templateFile() function in your .php file to point to your new template. /**
* Define the smarty template used to layout the search form and results listings.
*/
function templateFile( ) {
return 'CRM/Contact/Form/Search/Custom/Sample.tpl';
}
Test your search.
Drupal: http://<your site>-/civicrm/contact/search/custom?csid=6&reset=1 \\ Joomla: http://<your site>-/administrator/index2.php?option=com_civicrm&task=civicrm/contact/search/custom&csid=6&reset=1 If you're not getting expected results, you can print out the SQL query being issued from the search form by adding these lines just before the return statement at the end of the all() function: CRM_Core_Error::debug('sql',$sql);
exit();
If your search returns too many rows check that function all has a LIMIT statement appended to the sql: if ( $rowcount > 0 && $offset >= 0 ) { $sql .= " LIMIT $offset, $rowcount "; } |
