Commit 6fadc78f authored by colemanw's avatar colemanw
Browse files

Merge pull request #6738 from eileenmcnaughton/CRM-17075

CRM-17075 convert membership_type_id field to entity_reference field in search
parents 324f5f27 7fbb65da
......@@ -1465,15 +1465,23 @@ class CRM_Contact_BAO_Query {
*
* @param string $apiEntity
*
* @param array $entityReferenceFields
* Field names of any entity reference fields (which will need reformatting to IN syntax).
*
* @return array
*/
public static function convertFormValues(&$formValues, $wildcard = 0, $useEquals = FALSE, $apiEntity = NULL) {
public static function convertFormValues(&$formValues, $wildcard = 0, $useEquals = FALSE, $apiEntity = NULL,
$entityReferenceFields = array()) {
$params = array();
if (empty($formValues)) {
return $params;
}
foreach ($formValues as $id => $values) {
if (self::isAlreadyProcessedForQueryFormat($values)) {
$params[] = $values;
continue;
}
if ($id == 'privacy') {
if (is_array($formValues['privacy'])) {
$op = !empty($formValues['privacy']['do_not_toggle']) ? '=' : '!=';
......@@ -1526,6 +1534,10 @@ class CRM_Contact_BAO_Query {
continue;
}
}
elseif (in_array($id, $entityReferenceFields) && !empty($values) && is_string($values) && (strpos($values, ',') !=
FALSE)) {
$params[] = array($id, 'IN', explode(',', $values), 0, 0);
}
else {
$values = CRM_Contact_BAO_Query::fixWhereValues($id, $values, $wildcard, $useEquals, $apiEntity);
......@@ -4392,6 +4404,30 @@ civicrm_relationship.is_permission_a_b = 0
);
}
/**
* Has this field already been reformatting to Query object syntax.
*
* The form layer passed formValues to this function in preProcess & postProcess. Reason unknown. This seems
* to come with associated double queries & is possibly damaging performance.
*
* However, here we add a tested function to ensure convertFormValues identifies pre-processed fields & returns
* them as they are.
*
* @param mixed $values
* Value in formValues for the field.
*
* @return bool;
*/
protected static function isAlreadyProcessedForQueryFormat($values) {
if (!is_array($values)) {
return FALSE;
}
if (($operator = CRM_Utils_Array::value(1, $values)) == FALSE) {
return FALSE;
}
return in_array($operator, CRM_Core_DAO::acceptedSQLOperators());
}
/**
* Create and query the db for an contact search.
*
......
......@@ -79,6 +79,16 @@ class CRM_Core_Form_Search extends CRM_Core_Form {
*/
protected $_taskList = array();
/**
* Declare entity reference fields as they will need to be converted.
*
* The entity reference format looks like '2,3' whereas the Query object expects array(2, 3)
* or array('IN' => array(2, 3). The latter is the one we are moving towards standardising on.
*
* @var array
*/
protected $entityReferenceFields = array();
/**
* Builds the list of tasks or actions that a searcher can perform on a result set.
*
......
......@@ -409,6 +409,13 @@ class CRM_Member_BAO_Query {
'class' => 'crm-select2',
));
$form->addEntityRef('membership_type_id', ts('Membership Type(s)'), array(
'entity' => 'MembershipType',
'multiple' => TRUE,
'placeholder' => ts('- any -'),
'select' => array('minimumInputLength' => 0),
));
$form->addElement('text', 'member_source', ts('Source'));
CRM_Core_Form_Date::buildDateRange($form, 'member_join_date', 1, '_low', '_high', ts('From'), FALSE);
......
......@@ -68,6 +68,13 @@ class CRM_Member_Form_Search extends CRM_Core_Form_Search {
*/
protected $_prefix = "member_";
/**
* Declare entity reference fields as they will need to be converted to using 'IN'.
*
* @var array
*/
protected $entityReferenceFields = array('membership_type_id');
/**
* Processing needed for buildForm and later.
*/
......@@ -114,7 +121,7 @@ class CRM_Member_Form_Search extends CRM_Core_Form_Search {
);
}
$this->_queryParams = CRM_Contact_BAO_Query::convertFormValues($this->_formValues);
$this->_queryParams = CRM_Contact_BAO_Query::convertFormValues($this->_formValues, 0, FALSE, NULL, $this->entityReferenceFields);
$selector = new CRM_Member_Selector_Search($this->_queryParams,
$this->_action,
NULL,
......@@ -197,7 +204,7 @@ class CRM_Member_Form_Search extends CRM_Core_Form_Search {
CRM_Core_BAO_CustomValue::fixCustomFieldValue($this->_formValues);
$this->_queryParams = CRM_Contact_BAO_Query::convertFormValues($this->_formValues);
$this->_queryParams = CRM_Contact_BAO_Query::convertFormValues($this->_formValues, 0, FALSE, NULL, $this->entityReferenceFields);
$this->set('formValues', $this->_formValues);
$this->set('queryParams', $this->_queryParams);
......
<?php
require_once 'CiviTest/CiviUnitTestCase.php';
/**
* Include dataProvider for tests
*/
class CRM_Member_BAO_QueryTest extends CiviUnitTestCase {
/**
* Set up function.
*
* Ensure CiviCase is enabled.
*/
public function setUp() {
parent::setUp();
CRM_Core_BAO_ConfigSetting::enableComponent('CiviCase');
}
/**
* Check that membership type is handled.
*
* We want to see the following syntaxes for membership_type_id field handled:
* 1) membership_type_id => 1
*/
public function testConvertEntityFieldSingleValue() {
$formValues = array('membership_type_id' => 2);
$params = CRM_Contact_BAO_Query::convertFormValues($formValues, 0, FALSE, NULL, array('membership_type_id'));
$this->assertEquals(array('membership_type_id', '=', 2, 0, 0), $params[0]);
$obj = new CRM_Contact_BAO_Query($params);
$this->assertEquals(array('civicrm_membership.membership_type_id = 2'), $obj->_where[0]);
}
/**
* Check that membership type is handled.
*
* We want to see the following syntaxes for membership_type_id field handled:
* 2) membership_type_id => 5,6
*
* The last of these is the format used prior to converting membership_type_id to an entity reference field.
*/
public function testConvertEntityFieldMultipleValueEntityRef() {
$formValues = array('membership_type_id' => '1,2');
$params = CRM_Contact_BAO_Query::convertFormValues($formValues, 0, FALSE, NULL, array('membership_type_id'));
$this->assertEquals(array('membership_type_id', 'IN', array(1, 2), 0, 0), $params[0]);
$obj = new CRM_Contact_BAO_Query($params);
$this->assertEquals(array('civicrm_membership.membership_type_id IN ("1", "2")'), $obj->_where[0]);
}
/**
* Check that membership type is handled.
*
* We want to see the following syntaxes for membership_type_id field handled:
* 3) membership_type_id => array(5,6)
*
* The last of these is the format used prior to converting membership_type_id to an entity reference field. It will
* be used by pre-existing smart groups.
*/
public function testConvertEntityFieldMultipleValueLegacy() {
$formValues = array('membership_type_id' => array(1, 2));
$params = CRM_Contact_BAO_Query::convertFormValues($formValues, 0, FALSE, NULL, array('membership_type_id'));
$this->assertEquals(array('membership_type_id', 'IN', array(1, 2), 0, 0), $params[0]);
$obj = new CRM_Contact_BAO_Query($params);
$this->assertEquals(array('civicrm_membership.membership_type_id IN ("1", "2")'), $obj->_where[0]);
}
/**
* Check that running convertFormValues more than one doesn't mangle the array.
*
* Unfortunately the convertFormValues & indeed much of the query code is run in pre-process AND post-process.
*
* The convertFormValues function should cope with this until such time as we can rationalise that.
*/
public function testConvertEntityFieldMultipleValueEntityRefDoubleRun() {
$formValues = array('membership_type_id' => '1,2');
$params = CRM_Contact_BAO_Query::convertFormValues($formValues, 0, FALSE, NULL, array('membership_type_id'));
$this->assertEquals(array('membership_type_id', 'IN', array(1, 2), 0, 0), $params[0]);
$params = CRM_Contact_BAO_Query::convertFormValues($params, 0, FALSE, NULL, array('membership_type_id'));
$this->assertEquals(array('membership_type_id', 'IN', array(1, 2), 0, 0), $params[0]);
$obj = new CRM_Contact_BAO_Query($params);
$this->assertEquals(array('civicrm_membership.membership_type_id IN ("1", "2")'), $obj->_where[0]);
}
}
......@@ -1388,4 +1388,20 @@ class api_v3_MembershipTest extends CiviUnitTestCase {
}
/**
* Test that all membership types are returned when getoptions is called.
*
* This test locks in current behaviour where types for all domains are returned. It should possibly be domain
* specific but that should only be done in conjunction with adding a hook to allow that to be altered as the
* multisite use case expects the master domain to be able to see all sites.
*
* See CRM-17075.
*/
public function testGetOptionsMembershipTypeID() {
$options = $this->callAPISuccess('Membership', 'getoptions', array('field' => 'membership_type_id'));
$this->assertEquals('General', array_pop($options['values']));
$this->assertEquals('General', array_pop($options['values']));
$this->assertEquals(NULL, array_pop($options['values']));
}
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment