diff --git a/CHANGELOG.md b/CHANGELOG.md index e14ac63..c377f29 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,9 +1,12 @@ -# auto_populate_fields 2.6.4 (released 2024-09-23) +# auto_populate_fields 2.6.5 (released 2024-09-23) - Run code formatter on ExternalModule.php (@pbchase, #70) - Fix typo in the module (@saipavan10-git, #70) - Fix #66 (@saipavan10-git, #70) - Fix the bug introduced by adding null coalescing (@saipavan10-git, #70) +# auto_populate_fields 2.6.4 (released 2024-09-23) +- null release + # auto_populate_fields 2.6.3 (released 2024-09-16) - Add zenodo.json and update the authors block in config (@saipavan10-git, #67, #68) - Fix #66 (@saipavan10-git, #66, #68) diff --git a/ExternalModule.php b/ExternalModule.php index 2898b57..d71c367 100644 --- a/ExternalModule.php +++ b/ExternalModule.php @@ -1,8 +1,10 @@ initializeJsObject(); if (PAGE == 'Design/online_designer.php') { $this->includeJs('js/helper.js'); - } - elseif ( (PAGE == 'DataEntry/index.php' || PAGE == 'surveys/index.php') && !empty($_GET['id']) ) { + } elseif ((PAGE == 'DataEntry/index.php' || PAGE == 'surveys/index.php') && !empty($_GET['id'])) { if (!$this->currentFormHasData()) { $this->setDefaultValues(); } - if (isset($_GET['page']) && (function_exists('getBranchingFields') || method_exists('\DataEntry', 'getBranchingFields')) ) { + if (isset($_GET['page']) && (function_exists('getBranchingFields') || method_exists('\DataEntry', 'getBranchingFields'))) { $this->setDefaultWhenVisible(); } } @@ -45,20 +48,19 @@ function redcap_every_page_top($project_id) { // Because REDCap does not recognize custom action tags this block appends // the REDCap action tag @DEFAULT in the case that any custom actions tags (@DEFAULT-*) // have been applied to a field. - function redcap_survey_page_top($project_id) { + function redcap_survey_page_top($project_id) + { $project_settings = $this->getProjectSettings(); if (!$project_settings['use_in_survey']) return; global $elements; // set the action_tag_class as it would be in the DataEntry context - foreach( $elements as &$element) { - $element['name'] ??=[]; - $this->survey_APF_fields ??=[]; + foreach ($elements as &$element) { $i = array_search($element['name'], $this->survey_APF_fields); - if ( $i !== false ) { + if ($i !== false) { // append to preserve existing tags. This can result in duplicate @DEFAULT action tags but there appear to be no affects from this $element['action_tag_class'] .= " @DEFAULT"; unset($this->survey_APF_fields[$i]); - if ( empty($this->survey_APF_fields) ) break; + if (empty($this->survey_APF_fields)) break; } } } @@ -73,7 +75,8 @@ function redcap_survey_page_top($project_id) { * - Piping on choice selection fields now returns the option key instead * of the option label. */ - function setDefaultValues() { + function setDefaultValues() + { global $Proj, $user_rights, $double_data_entry; // Storing old metadata. @@ -82,7 +85,6 @@ function setDefaultValues() { // Temporarily overriding project metadata. foreach ($Proj->metadata as $field_name => $field_info) { // Overriding choice selection fields - checkboxes, radios and dropdowns. - $field_info['element_type'] ??= ''; if (!in_array($field_info['element_type'], ['checkbox', 'radio', 'select'])) { continue; } @@ -90,7 +92,7 @@ function setDefaultValues() { if (!$options = parseEnum($Proj->metadata[$field_name]['element_enum'])) { continue; } - $options ??= []; + foreach (array_keys($options) as $key) { // Replacing selection choices labels with keys. $options[$key] = $key . ',' . $key; @@ -122,7 +124,7 @@ function setDefaultValues() { GROUP BY event_id ORDER BY log_event_id "; - + $params = [$_GET['id'], $Proj->project_id]; $result = $this->query($sql, $params); @@ -131,137 +133,135 @@ function setDefaultValues() { $events[] = $row['event_id']; } } - } - else { + } else { $arm = $Proj->eventInfo[$_GET['event_id']]['arm_num']; - $Proj->events[$arm]['events'] ??= []; $events = array_keys($Proj->events[$arm]['events']); } } $fields = empty($_GET['page']) ? $Proj->metadata : $Proj->forms[$_GET['page']]['fields']; $entry_num = ($double_data_entry && $user_rights['double_data'] != 0) ? '--' . $user_rights['double_data'] : ''; - $fields ??= []; - foreach (array_keys($fields) as $field_name) { - $field_info = $Proj->metadata[$field_name]; - $misc = $field_info['misc']; - - // Getting available action tags. - $action_tags = $this->getMultipleActionTagsQueue($action_tags_to_look, $misc); - if (empty($action_tags)) { - continue; - } - $default_value = ''; + if (isset($fields)) { + foreach (array_keys($fields) as $field_name) { + $field_info = $Proj->metadata[$field_name]; + $misc = $field_info['misc']; - // Looping over @DEFAULT_ and @DEFAULT-FROM-PREVIOUS-EVENT_ - // action tags. - foreach ($action_tags as $action_tag) { - if (strpos($action_tag, '@DEFAULT-FROM-PREVIOUS-EVENT') === 0) { - if (!$source_field = self::getValueInActionTag($misc, $action_tag)) { - // If no value is provided on the action tag, set the same - // field as source by default. - $source_field = $field_name; - } - elseif (!isset($Proj->metadata[$source_field])) { - // Invalid field. - continue; - } + // Getting available action tags. + $action_tags = $this->getMultipleActionTagsQueue($action_tags_to_look, $misc); + if (empty($action_tags)) { + continue; + } - $prev_event = false; - $source_form = $Proj->metadata[$source_field]['form_name']; + $default_value = ''; + + // Looping over @DEFAULT_ and @DEFAULT-FROM-PREVIOUS-EVENT_ + // action tags. + foreach ($action_tags as $action_tag) { + if (strpos($action_tag, '@DEFAULT-FROM-PREVIOUS-EVENT') === 0) { + if (!$source_field = self::getValueInActionTag($misc, $action_tag)) { + // If no value is provided on the action tag, set the same + // field as source by default. + $source_field = $field_name; + } elseif (!isset($Proj->metadata[$source_field])) { + // Invalid field. + continue; + } - // Getting previous event ID. - foreach ($events as $event) { - if ($event == $_GET['event_id']) { - break; + $prev_event = false; + $source_form = $Proj->metadata[$source_field]['form_name']; + + // Getting previous event ID. + foreach ($events as $event) { + if ($event == $_GET['event_id']) { + break; + } + // assign a data type to prevent PHP warning using null coalescing operator + $Proj->eventsForms[$event] ??= []; + + if (in_array($source_form, $Proj->eventsForms[$event])) { + $prev_event = $event; + } } - // assign a data type to prevent PHP warning using null coalescing operator - $Proj->eventsForms[$event] ??= []; - - if (in_array($source_form, $Proj->eventsForms[$event])) { - $prev_event = $event; + + if (!$prev_event) { + continue; } - } - if (!$prev_event) { - continue; - } + // Getting previous event value. + if (isset($data[$prev_event][$source_field])) { + $default_value = $data[$prev_event][$source_field]; + } elseif (isset($data['repeat_instances'][$prev_event][""])) { + // Handling repeat events by using the most recent instance of the previous event to source values + $most_recent_instance = array_slice($data['repeat_instances'][$prev_event][""], -1)[0]; + $default_value = $most_recent_instance[$source_field]; + } - // Getting previous event value. - if (isset($data[$prev_event][$source_field])) { - $default_value = $data[$prev_event][$source_field]; - } elseif (isset($data['repeat_instances'][$prev_event][""])) { - // Handling repeat events by using the most recent instance of the previous event to source values - $most_recent_instance = array_slice($data['repeat_instances'][$prev_event][""], -1)[0]; - $default_value = $most_recent_instance[$source_field]; + // Handling checkboxes case. + if (is_array($default_value)) { + $default_value = implode(',', array_keys(array_filter($default_value))); + } + } else { + if ($default_value = Form::getValueInQuotesActionTag($misc, $action_tag)) { + // Steping ahead REDCap and piping strings in our way. + $default_value = Piping::replaceVariablesInLabel($default_value, $_GET['id'] . $entry_num, $_GET['event_id'], $_GET['instance'], array(), false, null, false); + } } - // Handling checkboxes case. - if (is_array($default_value)) { - $default_value = implode(',', array_keys(array_filter($default_value))); - } - } - else { - if ($default_value = Form::getValueInQuotesActionTag($misc, $action_tag)) { - // Steping ahead REDCap and piping strings in our way. - $default_value = Piping::replaceVariablesInLabel($default_value, $_GET['id'] . $entry_num, $_GET['event_id'], $_GET['instance'], array(), false, null, false); + if (empty($default_value) && !is_numeric($default_value)) { + continue; } - } - if (empty($default_value) && !is_numeric($default_value)) { - continue; - } - - // Date data must follow Y-M-D regardless of how it is validated - // Piping support makes pulling the data stored in the source field difficult - $field_validation = $aux_metadata[$field_name]['element_validation_type']; - // if starts with 'date' - if (substr($field_validation, 0, 4) == 'date') { - switch($field_validation){ - case 'date_mdy': - $out_format = 'Y-m-d'; - $in_format = '!m-d-Y'; - break; - case 'date_dmy': - $out_format = 'Y-m-d'; - $in_format = '!d-m-Y'; - break; - case 'datetime_mdy': - $out_format = 'Y-m-d H:i'; - $in_format = 'm-d-Y H:i'; - break; - case 'datetime_dmy': - $out_format = 'Y-m-d H:i'; - $in_format = 'd-m-Y H:i'; - break; - case 'datetime_seconds_mdy': - $out_format = 'Y-m-d H:i:s'; - $in_format = 'm-d-Y H:i:s'; - break; - case 'datetime_seconds_dmy': - $out_format = 'Y-m-d H:i:s'; - $in_format = 'd-m-Y H:i:s'; - break; - default: - // break 2 or continue 2 do not continue after parent if - $in_format = 'ymd'; - break; - } - if ($in_format !== 'ymd') { - $date = \DateTime::createFromFormat($in_format, $default_value); - // This ternary prevents crashing for mixed source and target formats (e.g. YMD -> DMY) - // users will get validation errors - $default_value = $date ? $date->format($out_format) : $default_value; + // Date data must follow Y-M-D regardless of how it is validated + // Piping support makes pulling the data stored in the source field difficult + $field_validation = $aux_metadata[$field_name]['element_validation_type']; + // if starts with 'date' + if (substr($field_validation, 0, 4) == 'date') { + switch ($field_validation) { + case 'date_mdy': + $out_format = 'Y-m-d'; + $in_format = '!m-d-Y'; + break; + case 'date_dmy': + $out_format = 'Y-m-d'; + $in_format = '!d-m-Y'; + break; + case 'datetime_mdy': + $out_format = 'Y-m-d H:i'; + $in_format = 'm-d-Y H:i'; + break; + case 'datetime_dmy': + $out_format = 'Y-m-d H:i'; + $in_format = 'd-m-Y H:i'; + break; + case 'datetime_seconds_mdy': + $out_format = 'Y-m-d H:i:s'; + $in_format = 'm-d-Y H:i:s'; + break; + case 'datetime_seconds_dmy': + $out_format = 'Y-m-d H:i:s'; + $in_format = 'd-m-Y H:i:s'; + break; + default: + // break 2 or continue 2 do not continue after parent if + $in_format = 'ymd'; + break; + } + if ($in_format !== 'ymd') { + $date = \DateTime::createFromFormat($in_format, $default_value); + // This ternary prevents crashing for mixed source and target formats (e.g. YMD -> DMY) + // users will get validation errors + $default_value = $date ? $date->format($out_format) : $default_value; + } } - } - // The first non empty default value wins! - $misc = $this->overrideActionTag('@DEFAULT', $default_value, $misc); - $aux_metadata[$field_name]['misc'] = $misc; - array_push($this->survey_APF_fields, $field_name); + // The first non empty default value wins! + $misc = $this->overrideActionTag('@DEFAULT', $default_value, $misc); + $aux_metadata[$field_name]['misc'] = $misc; + array_push($this->survey_APF_fields, $field_name); - break; + break; + } } } @@ -283,14 +283,15 @@ function setDefaultValues() { * * @see js/default_when_visible.js */ - function setDefaultWhenVisible() { + function setDefaultWhenVisible() + { $equations = array(); - list($branching_fields, ) = (function_exists('getBranchingFields')) ? + list($branching_fields,) = (function_exists('getBranchingFields')) ? getBranchingFields($_GET['page']) : \DataEntry::getBranchingFields($_GET['page']); foreach ($branching_fields as $field => $equation) { - list($equations[$field], ) = LogicTester::formatLogicToJS($equation, false, $_GET['event_id'], true); + list($equations[$field],) = LogicTester::formatLogicToJS($equation, false, $_GET['event_id'], true); } // More current versions of REDCap do not have all js libraries loaded in time @@ -306,8 +307,9 @@ function setDefaultWhenVisible() { * @return bool * TRUE if the current form contains data, FALSE otherwise. */ - function currentFormHasData() { - global $double_data_entry, $user_rights, $quesion_by_section, $pageFields; + function currentFormHasData() + { + global $double_data_entry, $user_rights, $question_by_section, $pageFields; $record = $_GET['id']; if ($double_data_entry && $user_rights['double_data'] != 0) { @@ -340,7 +342,8 @@ function currentFormHasData() { * @return array * The sorted list of the fetched action tags. */ - function getMultipleActionTagsQueue($action_tags, $subject) { + function getMultipleActionTagsQueue($action_tags, $subject) + { $results = []; if (is_string($action_tags)) { @@ -405,13 +408,13 @@ function getMultipleActionTagsQueue($action_tags, $subject) { * @return string * The overriden subject string. */ - function overrideActionTag($key, $value, $subject, $append_if_not_exists = true) { + function overrideActionTag($key, $value, $subject, $append_if_not_exists = true) + { if (strpos($subject, $key . '=') !== false) { // Override action tag if exists. $regex = "/(' . $key . '\s*=\s*)((\"[^\"]+\")|(\'[^\']+\'))/"; $subject = preg_replace($regex, $key . '="' . $value . '"', $subject); - } - elseif ($append_if_not_exists) { + } elseif ($append_if_not_exists) { $subject .= ' ' . $key . '="' . $value . '"'; } @@ -424,7 +427,8 @@ function overrideActionTag($key, $value, $subject, $append_if_not_exists = true) * @param string $path * The relative path to the js file. */ - protected function includeJs($path) { + protected function includeJs($path) + { echo ''; } @@ -436,12 +440,14 @@ protected function includeJs($path) { * @param mixed $value * The setting value. */ - protected function setJsSetting($key, $value) { + protected function setJsSetting($key, $value) + { // initializeJsObject MUST be run once before this function echo ''; } - protected function initializeJsObject() { + protected function initializeJsObject() + { echo ''; } @@ -452,7 +458,8 @@ protected function initializeJsObject() { * * @see Form::getValueInActionTags() */ - public static function getValueInActionTag($subject, $action_tag) { + public static function getValueInActionTag($subject, $action_tag) + { if ($value = Form::getValueInQuotesActionTag($subject, $action_tag)) { return $value; } diff --git a/VERSION b/VERSION index 2714f53..57cf282 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -2.6.4 +2.6.5