diff --git a/Civi/Api4/Service/Spec/Provider/FileGetSpecProvider.php b/Civi/Api4/Service/Spec/Provider/FileGetSpecProvider.php
index 517eb61aeb0..06cadb99c2d 100644
--- a/Civi/Api4/Service/Spec/Provider/FileGetSpecProvider.php
+++ b/Civi/Api4/Service/Spec/Provider/FileGetSpecProvider.php
@@ -105,10 +105,10 @@ public static function renderFileUrl(array $idField, Api4SelectQuery $query): st
}
}
if (isset($entityIdField)) {
- return "CONCAT('civicrm/file?reset=1&id=', $idField[sql_name], '&eid=', $entityIdField[sql_name])";
+ return "CONCAT('civicrm/file?reset=1&id=', {$idField['sql_name']}, '&eid=', {$entityIdField['sql_name']})";
}
- // Guess we couldn't find an `entity_id` in the query. This function could probably be improved.
- return "NULL";
+ // Couldn't find an `entity_id` in the query so add a subquery instead.
+ return "CONCAT('civicrm/file?reset=1&id=', {$idField['sql_name']}, '&eid=', (SELECT `entity_id` FROM `civicrm_entity_file` WHERE `file_id` = {$idField['sql_name']} LIMIT 1))";
}
public static function renderFileIsImage(array $mimeTypeField, Api4SelectQuery $query): string {
diff --git a/ext/afform/core/Civi/Api4/Action/Afform/AbstractProcessor.php b/ext/afform/core/Civi/Api4/Action/Afform/AbstractProcessor.php
index 65a8df1763a..537b830f2d9 100644
--- a/ext/afform/core/Civi/Api4/Action/Afform/AbstractProcessor.php
+++ b/ext/afform/core/Civi/Api4/Action/Afform/AbstractProcessor.php
@@ -323,7 +323,7 @@ public function getJoinResult(array $afEntity, string $joinEntity, array $join,
}
/**
- * Delegated by loadEntity to call API.get and fill in additioal info
+ * Delegated by loadEntity to call API.get and fill in additional info
*
* @param string $afEntityName
* e.g. Individual1
@@ -343,10 +343,14 @@ private function apiGet($afEntityName, $apiEntityName, $entityFields, string $ke
// Fill additional info about file fields
$fileFields = $this->getFileFields($apiEntityName, $entityFields);
foreach ($fileFields as $fieldName => $fieldDefn) {
+ $select = ['file_name', 'icon'];
+ if ($this->canViewFileAttachments($afEntityName)) {
+ $select[] = 'url';
+ }
foreach ($result as &$item) {
if (!empty($item[$fieldName])) {
$fileInfo = File::get(FALSE)
- ->addSelect('file_name', 'icon')
+ ->setSelect($select)
->addWhere('id', '=', $item[$fieldName])
->execute()->first();
$item[$fieldName] = $fileInfo;
@@ -356,6 +360,11 @@ private function apiGet($afEntityName, $apiEntityName, $entityFields, string $ke
return $result;
}
+ private function canViewFileAttachments(string $afEntityName): bool {
+ $afEntity = $this->_formDataModel->getEntity($afEntityName);
+ return ($afEntity['security'] === 'FBAC' || \CRM_Core_Permission::check('access uploaded files'));
+ }
+
protected static function getFileFields($entityName, $entityFields): array {
if (!$entityFields) {
return [];
diff --git a/ext/afform/core/ang/af/fields/DisplayOnly.html b/ext/afform/core/ang/af/fields/DisplayOnly.html
index 7d4a6964710..e5ceaccc53c 100644
--- a/ext/afform/core/ang/af/fields/DisplayOnly.html
+++ b/ext/afform/core/ang/af/fields/DisplayOnly.html
@@ -1 +1,13 @@
-{{dataProvider.getFieldData()[$ctrl.fieldName]}}
+
+
+
+ {{ dataProvider.getFieldData()[$ctrl.fieldName].file_name }}
+
+
+
+ {{ dataProvider.getFieldData()[$ctrl.fieldName].file_name }}
+
+
+
+ {{ dataProvider.getFieldData()[$ctrl.fieldName] }}
+
diff --git a/ext/afform/core/ang/af/fields/File.html b/ext/afform/core/ang/af/fields/File.html
index 61447da1323..c9486b16431 100644
--- a/ext/afform/core/ang/af/fields/File.html
+++ b/ext/afform/core/ang/af/fields/File.html
@@ -1,6 +1,12 @@
-
- {{ dataProvider.getFieldData()[$ctrl.fieldName].file_name }}
+
+
+ {{ dataProvider.getFieldData()[$ctrl.fieldName].file_name }}
+
+
+
+ {{ dataProvider.getFieldData()[$ctrl.fieldName].file_name }}
+
diff --git a/tests/phpunit/api/v4/Custom/CustomFileTest.php b/tests/phpunit/api/v4/Custom/CustomFileTest.php
new file mode 100644
index 00000000000..6f005cce75f
--- /dev/null
+++ b/tests/phpunit/api/v4/Custom/CustomFileTest.php
@@ -0,0 +1,75 @@
+setValues([
+ 'title' => 'FileFields',
+ 'extends' => 'Individual',
+ ])->execute()->single();
+ $field = CustomField::create()->setValues([
+ 'label' => 'TestMyFile',
+ 'custom_group_id.name' => 'FileFields',
+ 'html_type' => 'File',
+ 'data_type' => 'File',
+ ])->execute()->single();
+
+ $fieldName = 'FileFields.TestMyFile';
+
+ $contact = $this->createTestRecord('Individual');
+
+ // FIXME: Use Api4 when available
+ $file = civicrm_api3('Attachment', 'create', [
+ // The mismatch between entity id and entity table feels very wrong but that's how core does it for now
+ 'entity_id' => $contact['id'],
+ 'entity_table' => $group['table_name'],
+ 'mime_type' => 'text/plain',
+ 'name' => 'test123.txt',
+ 'content' => 'Hello World 123',
+ ]);
+
+ civicrm_api4('Individual', 'update', [
+ 'values' => [
+ 'id' => $contact['id'],
+ $fieldName => $file['id'],
+ ],
+ 'checkPermissions' => FALSE,
+ ]);
+
+ $file = File::get(FALSE)
+ ->addSelect('id', 'file_name', 'url')
+ ->addWhere('id', '=', $file['id'])
+ ->execute()->single();
+
+ $this->assertEquals('test123.txt', $file['file_name']);
+ $this->assertStringContainsString("id={$file['id']}&eid={$contact['id']}&fcs=", $file['url']);
+ }
+
+}