continue;
}
$fieldExpr = SqlExpression::convert($selectAliases[$key] ?? $key);
- $fieldName = \CRM_Utils_Array::first($fieldExpr->getFields() ?? '');
+ $fieldName = \CRM_Utils_Array::first($fieldExpr->getFields());
$baseName = $fieldName ? \CRM_Utils_Array::first(explode(':', $fieldName)) : NULL;
$field = $fields[$fieldName] ?? $fields[$baseName] ?? NULL;
$dataType = $field['data_type'] ?? ($fieldName == 'id' ? 'Integer' : NULL);
- // Allow Sql Functions to do alter the value and/or $dataType
+ // Allow Sql Functions to alter the value and/or $dataType
if (method_exists($fieldExpr, 'formatOutputValue') && is_string($value)) {
$fieldExpr->formatOutputValue($dataType, $result, $key);
$value = $result[$key];
}
if (!empty($field['output_formatters'])) {
- self::applyFormatters($result, $fieldName, $field, $value);
+ self::applyFormatters($result, $fieldExpr, $field, $value);
$dataType = NULL;
}
// Evaluate pseudoconstant suffixes
* Apply a field's output_formatters callback functions
*
* @param array $result
- * @param string $fieldPath
- * @param array $field
+ * @param \Civi\Api4\Query\SqlExpression $fieldExpr
+ * @param array $fieldDefn
* @param mixed $value
*/
- private static function applyFormatters(array $result, string $fieldPath, array $field, &$value) {
- $row = self::filterByPath($result, $fieldPath, $field['name']);
+ private static function applyFormatters(array $result, SqlExpression $fieldExpr, array $fieldDefn, &$value): void {
+ $fieldPath = \CRM_Utils_Array::first($fieldExpr->getFields());
+ $row = self::filterByPath($result, $fieldPath, $fieldDefn['name']);
+
+ // For aggregated array data, apply the formatter to each item
+ if (is_array($value) && $fieldExpr->getType() === 'SqlFunction' && $fieldExpr::getCategory() === 'aggregate') {
+ foreach ($value as $index => &$val) {
+ $subRow = $row;
+ foreach ($row as $rowKey => $rowValue) {
+ if (is_array($rowValue) && array_key_exists($index, $rowValue)) {
+ $subRow[$rowKey] = $rowValue[$index];
+ }
+ }
+ self::applyFormatter($fieldDefn, $subRow, $val);
+ }
+ }
+ else {
+ self::applyFormatter($fieldDefn, $row, $value);
+ }
+ }
- foreach ($field['output_formatters'] as $formatter) {
- $formatter($value, $row, $field);
+ private static function applyFormatter(array $fieldDefn, array $row, &$value): void {
+ foreach ($fieldDefn['output_formatters'] as $formatter) {
+ $formatter($value, $row, $fieldDefn);
}
}
namespace api\v4\Action;
use api\v4\Api4TestBase;
+use Civi\Api4\Activity;
use Civi\Api4\EntityFile;
use Civi\Api4\File;
use Civi\Api4\Note;
$this->assertStringContainsString("id=$file[3]&eid=$note[3]&fcs=", $allowedNotes[$note[3]]['file.url']);
}
+ public function testGetAggregateFileFields() {
+ $activity = $this->createTestRecord('Activity');
+
+ foreach (['text/plain' => 'txt', 'image/png' => 'png', 'image/jpg' => 'jpg'] as $mimeType => $ext) {
+ // FIXME: Use api4 when available
+ civicrm_api3('Attachment', 'create', [
+ 'entity_table' => 'civicrm_activity',
+ 'entity_id' => $activity['id'],
+ 'name' => 'test_file.' . $ext,
+ 'mime_type' => $mimeType,
+ 'content' => 'hello',
+ ])['id'];
+ }
+
+ $get = Activity::get(FALSE)
+ ->addWhere('id', '=', $activity['id'])
+ ->addJoin('File AS file', 'LEFT', 'EntityFile', ['file.entity_id', '=', 'id'], ['file.entity_table', '=', '"civicrm_activity"'])
+ ->addGroupBy('id')
+ ->addSelect('GROUP_CONCAT(UNIQUE file.file_name) AS aggregate_file_name')
+ ->addSelect('GROUP_CONCAT(UNIQUE file.url) AS aggregate_url')
+ ->addSelect('GROUP_CONCAT(UNIQUE file.icon) AS aggregate_icon')
+ ->execute()->single();
+
+ $this->assertCount(3, $get['aggregate_url']);
+ $this->assertCount(3, $get['aggregate_icon']);
+ $this->assertEquals(['test_file.txt', 'test_file.png', 'test_file.jpg'], $get['aggregate_file_name']);
+ $this->assertEquals(['fa-file-text-o', 'fa-file-image-o', 'fa-file-image-o'], $get['aggregate_icon']);
+ }
+
}