* Leaf operators are one of:
*
* * '=', '<=', '>=', '>', '<', 'LIKE', "<>", "!=",
- * * "NOT LIKE", 'IN', 'NOT IN', 'BETWEEN', 'NOT BETWEEN',
- * * 'IS NOT NULL', or 'IS NULL'.
+ * * 'NOT LIKE', 'IN', 'NOT IN', 'BETWEEN', 'NOT BETWEEN',
+ * * 'IS NOT NULL', or 'IS NULL', 'CONTAINS'.
*/
class Api4SelectQuery {
}
$results[] = $result;
}
- FormattingUtil::formatOutputValues($results, $this->apiFieldSpec, $this->getEntity());
+ FormattingUtil::formatOutputValues($results, $this->apiFieldSpec, $this->getEntity(), 'get', $this->selectAliases);
return $results;
}
$suffix = strstr($item, ':');
if ($suffix && $expr->getType() === 'SqlField') {
$field = $this->getField($item);
- $options = FormattingUtil::getPseudoconstantList($field['entity'], $field['name'], substr($suffix, 1));
+ $options = FormattingUtil::getPseudoconstantList($field, substr($suffix, 1));
if ($options) {
asort($options);
$column = "FIELD($column,'" . implode("','", array_keys($options)) . "')";
$fieldAlias = $expr;
// Attempt to format if this is a real field
if (isset($this->apiFieldSpec[$expr])) {
- FormattingUtil::formatInputValue($value, $expr, $this->apiFieldSpec[$expr]);
+ $field = $this->getField($expr);
+ FormattingUtil::formatInputValue($value, $expr, $field);
}
}
// Expr references a non-field expression like a function; convert to alias
foreach ($this->selectAliases as $selectAlias => $selectExpr) {
list($selectField) = explode(':', $selectAlias);
if ($selectAlias === $selectExpr && $fieldName === $selectField && isset($this->apiFieldSpec[$fieldName])) {
- FormattingUtil::formatInputValue($value, $expr, $this->apiFieldSpec[$fieldName]);
+ $field = $this->getField($fieldName);
+ FormattingUtil::formatInputValue($value, $expr, $field);
$fieldAlias = $selectAlias;
break;
}
return sprintf('%s %s %s', $fieldAlias, $operator, $valExpr->render($this->apiFieldSpec));
}
elseif ($fieldName) {
- FormattingUtil::formatInputValue($value, $fieldName, $this->apiFieldSpec[$fieldName]);
+ $field = $this->getField($fieldName);
+ FormattingUtil::formatInputValue($value, $fieldName, $field);
+ }
+ }
+
+ if ($operator === 'CONTAINS') {
+ switch ($field['serialize'] ?? NULL) {
+ case \CRM_Core_DAO::SERIALIZE_JSON:
+ $operator = 'LIKE';
+ $value = '%"' . $value . '"%';
+ // FIXME: Use this instead of the above hack once MIN_INSTALL_MYSQL_VER is bumped to 5.7.
+ // return sprintf('JSON_SEARCH(%s, "one", "%s") IS NOT NULL', $fieldAlias, \CRM_Core_DAO::escapeString($value));
+ break;
+
+ case \CRM_Core_DAO::SERIALIZE_SEPARATOR_BOOKEND:
+ $operator = 'LIKE';
+ $value = '%' . \CRM_Core_DAO::VALUE_SEPARATOR . $value . \CRM_Core_DAO::VALUE_SEPARATOR . '%';
+ break;
+
+ default:
+ $operator = 'LIKE';
+ $value = '%' . $value . '%';
+ break;
}
}
}
/**
- * Join onto a BridgeEntity table
+ * Join onto a Bridge table
*
* @param array $joinTree
* @param string $joinEntity
*/
protected function getBridgeJoin(&$joinTree, $joinEntity, $alias) {
$bridgeEntity = array_shift($joinTree);
- if (!is_a('\Civi\Api4\\' . $bridgeEntity, '\Civi\Api4\Generic\BridgeEntity', TRUE)) {
+ /* @var \Civi\Api4\Generic\DAOEntity $bridgeEntityClass */
+ $bridgeEntityClass = '\Civi\Api4\\' . $bridgeEntity;
+ if (!in_array('EntityBridge', $bridgeEntityClass::getInfo()['type'], TRUE)) {
throw new \API_Exception("Illegal bridge entity specified: " . $bridgeEntity);
}
$bridgeAlias = $alias . '_via_' . strtolower($bridgeEntity);
$bridgeTable = CoreUtil::getTableName($bridgeEntity);
$joinTable = CoreUtil::getTableName($joinEntity);
- $bridgeEntityGet = \Civi\API\Request::create($bridgeEntity, 'get', ['version' => 4, 'checkPermissions' => $this->getCheckPermissions()]);
+ $bridgeEntityGet = $bridgeEntityClass::get($this->getCheckPermissions());
$fkToJoinField = $fkToBaseField = NULL;
// Find the bridge field that links to the joinEntity (either an explicit FK or an entity_id/entity_table combo)
foreach ($bridgeEntityGet->entityFields() as $name => $field) {