From a75c13cc91b86e33c8b8e6f15bbe2229ff8bc5f1 Mon Sep 17 00:00:00 2001 From: Eileen McNaughton Date: Sat, 24 May 2014 20:24:48 +1200 Subject: [PATCH] CRM-14743 add support for api operators to BAO query object (although at the end will be over-ruled by various other handlings, however, we are locking in by test --- CRM/Contact/BAO/Query.php | 16 +++++++++++++--- CRM/Core/DAO.php | 6 +++--- CRM/Utils/API/HTMLInputCoder.php | 2 ++ CRM/Utils/System.php | 2 ++ api/v3/utils.php | 10 ++++++++-- tests/phpunit/api/v3/ContactTest.php | 9 +++++++++ 6 files changed, 37 insertions(+), 8 deletions(-) diff --git a/CRM/Contact/BAO/Query.php b/CRM/Contact/BAO/Query.php index aca2545a17..58985301b8 100644 --- a/CRM/Contact/BAO/Query.php +++ b/CRM/Contact/BAO/Query.php @@ -2104,9 +2104,19 @@ class CRM_Contact_BAO_Query { $this->_qill[$grouping][] = "$field[title] $op \"$value\""; } else { - // sometime the value is an array, need to investigate and fix if (is_array($value)) { - CRM_Core_Error::fatal(); + // traditionally an array being passed has been a fatal error. We can take advantage of this to add support + // for api style operators for functions that hit this point without worrying about regression + // (the previous comments indicated the condition for hitting this point were unknown + // per CRM-14743 we are adding modified_date & created_date operator support + $operations = array_keys($value); + foreach ($operations as $operator) { + if(!in_array($operator, CRM_Core_DAO::acceptedSQLOperators())) { + // we don't know when this might happen + CRM_Core_Error::fatal(); + } + } + $value = CRM_Core_DAO::createSQLFilter($name, $value, NULL); } if (!empty($field['where'])) { @@ -5138,7 +5148,7 @@ SELECT COUNT( conts.total_amount ) as cancel_count, } $value = CRM_Utils_Type::escape($value, $dataType); - // if we dont have a dataType we should assume + // if we don't have a dataType we should assume if ($dataType == 'String' || $dataType == 'Text') { $value = "'" . strtolower($value) . "'"; } diff --git a/CRM/Core/DAO.php b/CRM/Core/DAO.php index f6eaaec768..ea88f50dc8 100644 --- a/CRM/Core/DAO.php +++ b/CRM/Core/DAO.php @@ -2026,7 +2026,7 @@ SELECT contact_id * * @throws Exception * @internal param string $fieldname name of fields - * @todo a better solutution would be for the query object to apply these filters based on the + * @todo a better solution would be for the query object to apply these filters based on the * api supported format (but we don't want to risk breakage in alpha stage & query class is scary * @todo @time of writing only IN & NOT IN are supported for the array style syntax (as test is * required to extend further & it may be the comments per above should be implemented. It may be @@ -2049,7 +2049,7 @@ SELECT contact_id return (sprintf('%s %s', $fieldName, $operator)); } else{ - return NULL; // not yet implemented (tests required to implement) + return (sprintf('%s %s ', $fieldName, $operator)); } break; @@ -2103,7 +2103,7 @@ SELECT contact_id * @return array */ public static function acceptedSQLOperators() { - return array('=', '<=', '>=', '>', '<', 'LIKE', "<>", "!=", "NOT LIKE", 'IN', 'NOT IN', 'BETWEEN', 'NOT BETWEEN'); + return array('=', '<=', '>=', '>', '<', 'LIKE', "<>", "!=", "NOT LIKE", 'IN', 'NOT IN', 'BETWEEN', 'NOT BETWEEN', 'IS NOT NULL', 'IS NULL'); } /** diff --git a/CRM/Utils/API/HTMLInputCoder.php b/CRM/Utils/API/HTMLInputCoder.php index 86bd44b4b3..d34ee71b20 100644 --- a/CRM/Utils/API/HTMLInputCoder.php +++ b/CRM/Utils/API/HTMLInputCoder.php @@ -133,6 +133,8 @@ class CRM_Utils_API_HTMLInputCoder extends CRM_Utils_API_AbstractFieldCoder { /** * @param $values * @param bool $castToString + * + * @return mixed|void */ public function decodeOutput(&$values, $castToString = FALSE) { if (is_array($values)) { diff --git a/CRM/Utils/System.php b/CRM/Utils/System.php index 76a2c1dfab..403c2ab8d9 100644 --- a/CRM/Utils/System.php +++ b/CRM/Utils/System.php @@ -183,6 +183,8 @@ class CRM_Utils_System { * @param bool $maintenance * (optional) For maintenance mode. * + * @return string + * * @access public */ static function theme( diff --git a/api/v3/utils.php b/api/v3/utils.php index 29ebc64b5d..15ee63310b 100644 --- a/api/v3/utils.php +++ b/api/v3/utils.php @@ -538,6 +538,13 @@ function _civicrm_api3_get_query_object($params, $mode, $entity) { /** * Function transfers the filters being passed into the DAO onto the params object + * @param CRM_Core_DAO $dao + * @param array $params + * @param bool $unique + * @param string $entity + * + * @throws API_Exception + * @throws Exception */ function _civicrm_api3_dao_set_filter(&$dao, $params, $unique = TRUE, $entity) { $entity = substr($dao->__table, 8); @@ -1658,11 +1665,10 @@ function _civicrm_api3_validate_html(&$params, &$fieldName, &$fieldInfo) { * Validate string fields being passed into API. * @param array $params params from civicrm_api * @param string $fieldName uniquename of field being checked - * @param $fieldInfo + * @param array $fieldInfo array of fields from getfields function * @param $entity * @throws API_Exception * @throws Exception - * @internal param array $fieldinfo array of fields from getfields function */ function _civicrm_api3_validate_string(&$params, &$fieldName, &$fieldInfo, $entity) { // If fieldname exists in params diff --git a/tests/phpunit/api/v3/ContactTest.php b/tests/phpunit/api/v3/ContactTest.php index 1b9c84e995..cff73f0aa1 100644 --- a/tests/phpunit/api/v3/ContactTest.php +++ b/tests/phpunit/api/v3/ContactTest.php @@ -1791,4 +1791,13 @@ class api_v3_ContactTest extends CiviUnitTestCase { $this->assertTrue(!isset($refCountsIdx['sql:civicrm_address:contact_id'])); } + function testSQLOperatorsOnContactAPI() { + $this->individualCreate(); + $this->organizationCreate(); + $this->householdCreate(); + $contacts = $this->callAPISuccess('contact', 'get', array('legal_name' => array('IS NOT NULL' => TRUE))); + $this->assertEquals($contacts['count'], CRM_Core_DAO::singleValueQuery('select count(*) FROM civicrm_contact WHERE legal_name IS NOT NULL')); + $contacts = $this->callAPISuccess('contact', 'get', array('legal_name' => array('IS NULL' => TRUE))); + $this->assertEquals($contacts['count'], CRM_Core_DAO::singleValueQuery('select count(*) FROM civicrm_contact WHERE legal_name IS NULL')); + } } -- 2.25.1