//Check if it's a valid date if (!checkdate($_GET['month'], $_GET['day'], $_GET['year'])) { exit("<b>{$lang['global_01']}{$lang['colon']}</b><br>{$lang['calendar_popup_19']}"); } print "<div style='color:green;font-family:verdana;padding:5px;margin-bottom:10px;font-weight:bold;font-size:16px;border-bottom:1px solid #aaa;'>\n\t\t\t\t{$lang['calendar_popup_20']}</div>\n\t\t\t\n\t\t\t<form method='post' action='{$_SERVER['PHP_SELF']}?pid={$project_id}&width=600' name='form'>\n\t\t\t<table style='font-family:Arial;font-size:14px;' cellpadding='0' cellspacing='10'>"; // Show option to attach calendar event to a record (i.e. unscheduled cal event) if ($_GET['record'] != "") { $_GET['record'] = strip_tags(label_decode($_GET['record'])); print "\n\t\t\t<tr>\n\t\t\t\t<td valign='top'>{$table_pk_label}: </td>\n\t\t\t\t<td valign='top'>\n\t\t\t\t\t<b>" . RCView::escape(removeDDEending($_GET['record'])) . "</b>\n\t\t\t\t\t<input type='hidden' name='idnumber' value='" . RCView::escape($_GET['record']) . "'>\n\t\t\t\t</td>\n\t\t\t</tr>"; } print "<tr>\n\t\t\t\t<td valign='top'>{$lang['global_18']}{$lang['colon']}</td>\n\t\t\t\t<td valign='top'>\n\t\t\t\t\t<b>" . DateTimeRC::format_ts_from_ymd($event_date) . " (" . DateTimeRC::getDay($event_date) . ")</b>\n\t\t\t\t\t<input type='hidden' id='event_date' name='event_date' value='{$event_date}'>\n\t\t\t\t</td>\n\t\t\t</tr>\n\t\t\t<tr>\n\t\t\t\t<td valign='top'>\n\t\t\t\t\t{$lang['global_13']}{$lang['colon']}\n\t\t\t\t\t<div style='font-size:10px;color:#888;'>{$lang['global_06']}</div>\n\t\t\t\t</td>\n\t\t\t\t<td valign='top'>\n\t\t\t\t\t<input type='text' class='x-form-text x-form-field time' id='event_time' name='event_time' maxlength='5' style='width:50px;' onblur=\"redcap_validate(this,'','','soft_typed','time')\"> \n\t\t\t\t\t<span style='font-size:10px;color:#777;font-family:tahoma;'>HH:MM ({$lang['calendar_popup_22']})</span>\n\t\t\t\t</td>\n\t\t\t</tr>\n\t\t\t<tr>\n\t\t\t\t<td valign='top'>{$lang['calendar_popup_11']}{$lang['colon']}</td>\n\t\t\t\t<td valign='top'><textarea id='notes' name='notes' class='x-form-textarea x-form-field' style='font-size:12px;width:400px;height:100px;'>{$row['notes']}</textarea></td>\n\t\t\t</tr>"; // Show option to attach calendar event to a record (i.e. unscheduled cal event) if ($_GET['record'] == "") { print "<tr>\n\t\t\t\t\t<td valign='top'>{$table_pk_label}: </td>\n\t\t\t\t\t<td>\n\t\t\t\t\t\t<table cellpadding=0 cellspacing=0><tr>\n\t\t\t\t\t\t<td valign='top'>\n\t\t\t\t\t\t\t<select name='idnumber' id='idnumber' class='x-form-text x-form-field' style='height:22px;padding-right:0;font-size:11px;'>\n\t\t\t\t\t\t\t<option value=''> - {$lang['calendar_popup_23']} - </option>"; // Retrieve record list (exclude non-DAG records if user is in a DAG) foreach (array_keys(Records::getData('array', array(), $table_pk, array(), $user_rights['group_id'])) as $this_record) { print "\t\t\t<option value='{$this_record}'>" . removeDDEending($this_record) . "</option>"; } print "\t\t\t</select>\n\t\t\t\t\t\t</td>\n\t\t\t\t\t\t<td valign='top' style='font-size:11px;color:#666;padding-left:10px;'>\n\t\t\t\t\t\t\t{$lang['calendar_popup_24']} {$table_pk_label}\n\t\t\t\t\t\t</td>\n\t\t\t\t\t\t</tr></table>\n\t\t\t\t\t</td>\n\t\t\t\t</tr>"; } print "<tr>\n\t\t\t\t<td></td>\n\t\t\t\t<td valign='top'>\n\t\t\t\t\t<br><br>\n\t\t\t\t\t<input type='submit' value='{$lang['calendar_popup_25']}' onclick=\"\n\t\t\t\t\t\tif (document.getElementById('notes').value.length < 1) {\n\t\t\t\t\t\t\talert('{$lang['calendar_popup_26']}');\n\t\t\t\t\t\t\treturn false;\t\t\t\t\t\t\n\t\t\t\t\t\t}\n\t\t\t\t\t\">\n\t\t\t\t\t<br><br>\n\t\t\t\t</td>\n\t\t\t</tr>\n\t\t\t</table>\n\t\t\t</form>"; /** * DISPLAY CONFIRMATION THAT NEW CALENDAR EVENT WAS CREATED */ } elseif (!isset($_GET['cal_id']) && !empty($_POST)) { //If an existing record was selected, make sure record doesn't already exist in a DAG. If so, add its group_id to calendar event. if ($_POST['idnumber'] != "") { $group_id = db_result(db_query("select value from redcap_data where project_id = {$project_id} and record = '{$_POST['idnumber']}' and field_name = '__GROUPID__' limit 1"), 0); //If did not select a record, check if user is in DAG. } elseif ($user_rights['group_id'] != "") { $group_id = $user_rights['group_id'];
public static function applyFilteringLogic($logic, $records = array(), $project_id = null) { // Skip this if no filtering will be performed if ($logic == '') { return false; } // Get or create $Proj object if (is_numeric($project_id)) { // Instantiate object containing all project information // This only occurs when calling getData for a project in a plugin in another project's context $Proj = new Project($project_id); } else { // Set global var global $Proj; } // Place record list in array $records_filtered = array(); // Parse the label to pull out the events/fields used therein $fields = array_keys(getBracketedFields($logic, true, true, false)); // If no fields were found in string, then return the label as-is if (empty($fields)) { return false; } // Instantiate logic parse $parser = new LogicParser(); // Check syntax of logic string: If there is an issue in the logic, then return false and stop processing // if (!LogicTester::isValid($logic)) return false; // Loop through fields, and if is longitudinal with prepended event names, separate out those with non-prepended fields $events = array(); $fields_classic = array(); $fields_no_events = array(); foreach ($fields as $this_key => $this_field) { // If longitudinal with a dot, parse it out and put unique event name in $events array if (strpos($this_field, '.') !== false) { // Separate event from field list($this_event, $this_field) = explode(".", $this_field, 2); // Add field to fields_no_events array $fields_no_events[] = $this_field; // Put event in $events array $this_event_id = $Proj->getEventIdUsingUniqueEventName($this_event); if (!isset($events[$this_event_id])) { $events[$this_event_id] = $this_event; } } else { // Add field to fields_no_events array $fields_no_events[] = $fields_classic[] = $this_field; } } // Perform unique on $events and $fields arrays $fields_no_events = array_unique($fields_no_events); $fields_classic = array_unique($fields_classic); // If a longitudinal project and some fields in logic are to be evaluated on ALL events, then include all events $hasLongitudinalAllEventLogic = false; if ($Proj->longitudinal && !empty($fields_classic)) { $events = $Proj->getUniqueEventNames(); // Add flag to denote that some fields need to be checked for ALL events $hasLongitudinalAllEventLogic = true; } // Get all data for these records, fields, events $eventsGetData = empty($events) ? array_keys($Proj->eventInfo) : array_keys($events); // Longitudinal Reports- use the ordinary Records::getData as this version // is modified for row=record results, not row=record-events! //$record_data = self::getData($Proj->project_id, 'array', $records, array_merge(array($Proj->table_pk), $fields_no_events), $eventsGetData); $record_data = Records::getData($Proj->project_id, 'array', $records, array_merge(array($Proj->table_pk), $fields_no_events), $eventsGetData); // Due to issues where a record contains only BLANK values for the fields $fields_no_events, the record will be removed. // In this case, re-add that record manually as empty to allow logic parsing to work as intended. $blank_records = array_diff($records, array_keys($record_data)); if (!empty($blank_records)) { foreach ($blank_records as $this_record) { foreach ($eventsGetData as $this_event_id) { foreach ($fields_no_events as $this_field) { $record_data[$this_record][$this_event_id][$this_field] = ''; } } } } // LongitudinalReports - need to add missing events too... foreach ($record_data as $this_record_id => $this_record) { $blank_events = array_diff(array_keys($events), array_keys($this_record)); if (!empty($blank_events)) { foreach ($blank_events as $this_event_id) { foreach ($fields_no_events as $this_field) { $record_data[$this_record_id][$this_event_id][$this_field] = ''; } } } } // Place all logic functions in array so we can call them quickly $logicFunctions = array(); // Loop through all relevent events and build event-specific logic and anonymous logic function $event_ids = array_flip($events); /* if ($Proj->longitudinal) { // Longitudinal foreach ($events as $this_event_id=>$this_unique_event) { // Customize logic for this event (longitudinal only) if ($hasLongitudinalAllEventLogic) { $this_logic = LogicTester::logicPrependEventName($logic, $events[$this_event_id]); } else { $this_logic = $logic; } // Generate logic function and argument map try { list ($funcName, $argMap) = $parser->parse($this_logic, $event_ids); } catch(ErrorException $e) { return false; } // Add to array $logicFunctions[$this_event_id] = array('funcName'=>$funcName, 'argMap'=>$argMap); //, 'code'=>$parser->generatedCode); } } else { // Classic */ // Longitudinal Reports - row per participant so evaluate across events // Generate logic function and argument map try { list($funcName, $argMap) = $parser->parse($logic, $event_ids); } catch (ErrorException $e) { return false; } // Add to array // incl generated code for info $logicFunctions[$Proj->firstEventId] = array('funcName'=>$funcName, 'argMap'=>$argMap); //, 'code'=>$parser->generatedCode); $logicFunctions[$Proj->firstEventId] = array('funcName' => $funcName, 'argMap' => $argMap, 'code' => $parser->generatedCode); // } // Loop through each record-event and apply logic $records_logic_true = array(); foreach ($record_data as $this_record => &$event_data) { /* No NOT loop through events, just records! * // Loop through events in this record foreach (array_keys($event_data) as $this_event_id) { // Execute the logic to return boolean (return TRUE if is 1 and not 0 or FALSE) $logicValid = (LogicTester::applyLogic($logicFunctions[$this_event_id]['funcName'], $logicFunctions[$this_event_id]['argMap'], $event_data, $Proj->firstEventId) === 1); // Add record-event to array if logic is valid if ($logicValid) $record_events_logic_true[$this_record][$this_event_id] = true; } // Remove each record as we go to conserve memory unset($record_data[$this_record]); */ $this_event_id = $Proj->firstEventId; // Execute the logic to return boolean (return TRUE if is 1 and not 0 or FALSE) $logicValid = LogicTester::applyLogic($logicFunctions[$this_event_id]['funcName'], $logicFunctions[$this_event_id]['argMap'], $event_data, $Proj->firstEventId) === 1; // Add record to array if logic is valid if ($logicValid) { $records_logic_true[$this_record] = true; } // Remove each record as we go to conserve memory unset($record_data[$this_record]); } // Return array of records-events where logic is true return $records_logic_true; }