Skip to content
Open
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions modules/redcap/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -96,3 +96,16 @@ To be importable, the LORIS version of a REDCap instrument must:

Because the REDCap module imports REDCap instruments as LORIS LINST instruments, REDCap instruments must adhere to a few naming requirements to be LINST-compatible:
- A field name should not finish with `_status`.

## REDCap unique idnetifier field

REDCap defines a unique identifier field, sometimes called `Record ID` field. This field uniquely identifies a record and its name can be changed for each project.
As stated in the current REDCap documentation, it is defined as _"the first field of the first instrument, and if not using a template, the default is 'Record ID' [record_id]"_.

When exporting REDCap form data, it is also used to unlock a "hidden" feature, which adds several other metadata fields in the response, including:

- `redcap_event_name`: REDCap unique event name.
- `redcap_repeat_instrument`: in the case of repeated instruments, the instrument name.
- `redcap_repeat_instance`: in the case of repeated instruments, the instrument repeated instance number.

This is automatically set up during the client initialization and does not need any other set up.
61 changes: 60 additions & 1 deletion modules/redcap/php/client/redcaphttpclient.class.inc
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,13 @@ class RedcapHttpClient
*/
private array $_cache;

/**
* The record_id field name.
*
* @var string|null
*/
private ?string $_record_id_field_name;

/**
* Create a new REDCap Client for a specific REDCap instance and project.
*
Expand All @@ -85,6 +92,9 @@ class RedcapHttpClient
$this->_token = $project_api_token;
$this->_client = new Client($api_url);
$this->_verbose = $verbose;

// needs to be init
$this->_initRecordIDFieldName();
}

/**
Expand Down Expand Up @@ -817,7 +827,7 @@ class RedcapHttpClient
'forms' => $instrument_names,
// The 'record_id' parameter adds both the 'record_id' and
// 'redcap_event_name' fields to the REDCap records.
'fields' => ['record_id'],
'fields' => [$this->_record_id_field_name],
'events' => $unique_event_names,
'records' => $record_ids,
'rawOrLabel' => 'raw',
Expand All @@ -830,4 +840,53 @@ class RedcapHttpClient
// send request
return json_decode($this->_sendRequest($data), true);
}

/**
* Initialize the record ID field name from REDCap project.
* By default, it is defined as "record_id", but it can vary and be user-defined.
* The current documentation rule seems to be: "the record ID field name is
* accessible as the first field of the first instrument."
*
* @return void
*/
private function _initRecordIDFieldName(): void
{
// get the REDCap instrument list
$instruments = $this->getInstruments();
if (empty($instruments)) {
throw new \LorisException("[redcap] no instrument in the project");
}

// get the first instrument name
$first_instrument_name = $instruments[0]->name ?? null;
if ($first_instrument_name === null) {
throw new \LorisException("[redcap] cannot get the first instrument");
}

// get the dictionary of that instrument
$first_instrument_dictionary = $this->getDataDictionary(
[$first_instrument_name]
);
if (empty($first_instrument_dictionary)) {
throw new \LorisException(
"[redcap] cannot get the first instrument dictionary"
);
}

// get the dictionary item of "Record ID" field
$record_id_field = array_values(
array_filter(
$first_instrument_dictionary,
fn($dict_item) => $dict_item->field_label === "Record ID"
)
)[0] ?? null;
Comment thread
regisoc marked this conversation as resolved.
Outdated
if ($record_id_field === null) {
throw new \LorisException(
"[redcap] no 'record_id' designed field on REDCap"
);
}

// init the record id field name
$this->_record_id_field_name = $record_id_field->field_name;
}
}
Loading