diff --git a/CITATION.cff b/CITATION.cff index 66aa656..c7dafd6 100644 --- a/CITATION.cff +++ b/CITATION.cff @@ -5,6 +5,6 @@ authors: given-names: "Aidan" orcid: "https://orcid.org/0000-0001-9858-5470" title: "Requested and Required Fields" -doi: +doi: https://doi.org/10.5281/zenodo.11906079 date-released: 2024-06-17 url: "https://github.com/jangari/redcap_requested_and_required_fields" diff --git a/README.md b/README.md index 454b8c3..69edcb8 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,7 @@ # Requested and Required Fields +[![DOI](https://zenodo.org/badge/816116155.svg)](https://zenodo.org/doi/10.5281/zenodo.11906078) + This REDCap External Module provides functionality for requesting that respondents provide an answer to a field, and displays a warning to survey respondents if any requested fields are missing a value when they try to submit. For completeness, this module also allows required fields to be treated in the same way. Fields can be annotated with @REQUESTED or @REQUIRED, both of which take an optional description, which is shown to the user when they try to submit. If the description is omitted, the field label is shown instead. ![screencast](screencast.gif) @@ -12,7 +14,7 @@ This module does not play nicely with embedded fields. Perhaps this could be fix Unlike traditional required fields, wherein submitting the page commits other values to the database and sets the survey as partially complete, with this module enabled, clicking 'submit' does _not_ save any other entered values. Again, perhaps this could be fixed by running an AJAX call to save the data. -This module only considers fields to be required if they are annotated with @REQUIRED. It might be an idea in future to take fields marked Required in the designer and treat them in the same way. +~~This module only considers fields to be required if they are annotated with @REQUIRED. It might be an idea in future to take fields marked Required in the designer and treat them in the same way.~~ ## Installation @@ -33,6 +35,7 @@ This module can be configured with the following project settings: | Setting | Default Value | Description | | --- | --- | --- | +| Apply to fields marked as required in the project metadata? | false | If checked, fields marked as required in the data dictionary will be treated in the same way as though they were annotated with @REQUIRED. | | Modal title | "Action Required!" | Title of the popup window showing any requested or required fields. | | Requested text | "The following fields are requested, although you may submit without completing them:" | Text displayed in the modal window above listed requested fields. | | Required text | "The following fields are required:" | Text displayed in the modal window above listed requested fields. | @@ -47,3 +50,29 @@ This module can be configured with the following project settings: | Label requested fields | false | Display a label on requested fields. | | Requested field label text | "* response requested" | Text for requested field label. | | Requested field label colour | "#0000ff" (blue) | Colour for requested field label. | + +## Citation + +If you use this external module for a project that generates a research output, please cite this software in addition to [citing REDCap](https://projectredcap.org/resources/citations/) itself. You can do so using the APA referencing style as below: + +> Wilson, A. (2024). Requested and Required Fields [Computer software]. https://github.com/jangari/redcap_requested_and_required_fields https://doi.org/10.5281/zenodo.11906079 + +Or by adding this reference to your BibTeX database: + +```bibtex +@software{Wilson_Requested_and_Required_2024, + title = {{Requested and Required Fields}}, + author = {Wilson, Aidan}, + year = 2024, + month = 6, + url = {https://github.com/jangari/redcap_requested_and_required_fields} +} +``` +These instructions are also available in [GitHub](https://github.com/jangari/redcap_requested_and_required_fields/) under 'Cite This Repository'. + +## Changelog + +| Version | Description | +| --- | --- | +| 1.0.0 | Initial release. | +| 1.1.0 | Added support for fields marked as required in the project metadata. Fixes PHP8.0 compatibility. | diff --git a/RequestedAndRequiredFields.php b/RequestedAndRequiredFields.php index d2f118b..8a81aa8 100644 --- a/RequestedAndRequiredFields.php +++ b/RequestedAndRequiredFields.php @@ -1,6 +1,7 @@ getProjectSettings(); + // Get all annotated fields $requestedTag = "@REQUESTED"; $requiredTag = "@REQUIRED"; $tags = array($requestedTag, $requiredTag); $annotatedFields = $this->getTags($tags, $fields=NULL, $instruments=$instrument); - // Extract field names and build the new structure, with fieldType and description (or label if unset in the tag) + // Extract field names and build the new structure, with fieldType and description (or label if not set in the tag) $requestedFields = []; - foreach (array_keys($annotatedFields[$requestedTag]) as $fieldName) { + if (!empty($annotatedFields[$requestedTag]) && is_array($annotatedFields[$requestedTag])) { + foreach (array_keys($annotatedFields[$requestedTag]) as $fieldName) { $fieldType = REDCap::getFieldType($fieldName); $description = trim($annotatedFields[$requestedTag][$fieldName][0], '"'); - if (strlen($description) == 0) $description = $this->getFieldLabel($fieldName); + if (strlen($description) == 0) $description = $this->getFieldLabel($fieldName); $requestedFields[$fieldName] = [ 'type' => $fieldType, 'description' => $this->escape($description) ]; + }; }; $requiredFields = []; - foreach (array_keys($annotatedFields[$requiredTag]) as $fieldName) { + if (!empty($annotatedFields[$requiredTag]) && is_array($annotatedFields[$requiredTag])) { + foreach (array_keys($annotatedFields[$requiredTag]) as $fieldName) { $fieldType = REDCap::getFieldType($fieldName); $description = trim($annotatedFields[$requiredTag][$fieldName][0], '"'); if (strlen($description) == 0) $description = $this->getFieldLabel($fieldName); $requiredFields[$fieldName] = [ 'type' => $fieldType, - 'description' => $this->escape($description) + 'description' => strip_tags($description) ]; + }; }; - // Collect project settings - $settings = $this->getProjectSettings(); + // Add fields marked as required in the metadata to the requiredFields array + if ($settings['designer-required'] == '1'){ + $Proj = new Project($project_id); + // Loop through all fields in the current instrument + $instrumentFields = REDCap::getFieldNames($instrument=$instrument); + foreach ($instrumentFields as $this_field) { + // If the field is required AND it is not already in thr requiredFields array + if ($Proj->metadata[$this_field]['field_req'] == '1' && !array_key_exists($this_field, $requiredFields)){ + $fieldType = REDCap::getFieldType($this_field); // Get the type + $description = $this->getFieldLabel($this_field); // Get the label + $requiredFields[$this_field] = [ + 'type' => $fieldType, + 'description' => strip_tags($description) + ]; + }; + }; + }; + + // Sort requiredFields by the order of the fields in the instrument, using the instrumentFields array from earlier + $requiredFieldsSorted = []; + foreach ($instrumentFields as $field) { + if (isset($requiredFields[$field])) { + $requiredFieldsSorted[$field] = $requiredFields[$field]; + }; + }; + $requiredFields = $requiredFieldsSorted; + + // Let's stop if both requestedFields and requiredFields are empty + if (empty($requestedFields) && empty($requiredFields)){ + return; + }; // Language defaults $settings['modal-title'] = $settings['modal-title'] ?? $this->tt('modal-title-text'); diff --git a/config.json b/config.json index 47fdeb4..db2759d 100644 --- a/config.json +++ b/config.json @@ -23,6 +23,12 @@ } ], "project-settings": [ + { + "key": "designer-required", + "tt_name": "designer-required", + "name": "Apply to fields marked as required in the project metadata?", + "type": "checkbox" + }, { "key": "modal-title", "tt_name": "modal-title", diff --git a/lang/English.ini b/lang/English.ini index a4f9e2a..e94d188 100644 --- a/lang/English.ini +++ b/lang/English.ini @@ -3,6 +3,7 @@ name = "Requested and Required Fields" description = "Provides functionality for requesting a response to a field, and displays a warning to survey respondents if any requested fields are missing a value. For completeness, this module also allows required fields to be treated in the same way. Fields can be annotated with @REQUESTED or @REQUIRED, both of which take an optional description, which is shown to the user. If the description is omitted, the field label is shown instead." ; Configuration settings +designer-required = "Apply to fields marked as required in the project metadata?" modal-title = "Modal title
Title of window that pops up alerting the user to missing fields.
Default: Action Required!" modal-requested-header = "Modal header text for requested fields
Default: The following fields are requested, although you may submit without completing them:" modal-required-header = "Modal header text for required fields
Default: The following fields are required:"