コード例 #1
0
		while ($empty_row = db_fetch_assoc($empty_result)) {
			$history = Form::getDataHistoryLog($empty_row['record'], $empty_row['event_id'], $empty_row['field_name']);
			$all_fields_hidden = $my_branching_logic->allFieldsHidden($empty_row['record'], $empty_row['event_id'], array($empty_row['field_name']));
			if ($debug) {
				/**
				 * pick apart the hidden field logic - something's not right with fib_lbtest logic. ?'null'?
				 */
				$fieldsDependent = getDependentFields(array($empty_row['field_name']), false, true);
				$unique_event_name = $project->getUniqueEventNames($empty_row['event_id']);
				$record_data = Records::getSingleRecordData($empty_row['record'], array_merge($fieldsDependent, array($empty_row['field_name'])));
				$logic = $project->metadata[$empty_row['field_name']]['branching_logic'];
				if ($longitudinal) {
					$logic = LogicTester::logicPrependEventName($logic, $unique_event_name);
				}
				if (LogicTester::isValid($logic)) {
					$displayField = LogicTester::apply($logic, $record_data);
					$displayField = $displayField ? false : true;
				}
				show_var($fieldsDependent, 'DEP FIELDS');
				show_var($unique_event_name, 'unique event name');
				show_var($record_data, 'record data');
				show_var($logic, 'logic');
				show_var($displayField, 'all hidden?');
			}
			/**
			 * if all values are hidden for this field, delete the row.
			 */
			if ($all_fields_hidden) {
				$rows_deleted++;
				$delete_query = "DELETE FROM redcap_data WHERE record = '{$empty_row['record']}' AND project_id = '$project_id' AND event_id = '{$empty_row['event_id']}' AND field_name = '{$empty_row['field_name']}' AND value = '" . prep($empty_row['value']) . "'";
				if (!$debug) {
コード例 #2
0
 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;
 }
コード例 #3
0
	Stanford University

**/
global $end_survey_redirect_next_survey, $end_survey_redirect_url;
//hook_log($auto_continue_logic, "DEBUG", "Starting AutoContinueLogic!");
// Check if custom logic is applied to this instrument
if (isset($auto_continue_logic[$instrument])) {
    //hook_log("Applying auto-continue-logic to $instrument","DEBUG");
    // Get the logic and evaluate it
    $raw_logic = $auto_continue_logic[$instrument];
    $isValid = LogicTester::isValid($raw_logic);
    if (!$isValid) {
        print "<div class='red'><h3><center>Supplied survey auto-continue logic is invalid:<br>{$raw_logic}</center></h3></div>";
        hook_log("AutoContinue Logic is INVALID for {$project_id} / {$instrument}: {$raw_logic}", "ERROR");
    }
    $logic_result = LogicTester::evaluateLogicSingleRecord($raw_logic, $record);
    if ($logic_result == false) {
        // This instrument should not be taken!
        hook_log("AutoContinue Logic is FALSE - skipping {$instrument}", "DEBUG");
        // If autocontinue is enabled - then redirect to next instrument
        if ($end_survey_redirect_next_survey) {
            // Try to get the next survey url
            $next_survey_url = Survey::getAutoContinueSurveyUrl($record, $instrument, $event_id);
            //print "Redirecting you to $next_survey_url";
            hook_log("Redirecting {$record} from {$instrument} to {$next_survey_url}", "DEBUG");
            redirect($next_survey_url);
        } else {
            hook_log("AutoContinue Logic is FALSE for {$record} on {$instrument} but auto-continue is not enabled for this survey", "DEBUG");
            // If there is a normal end-of-survey url - go there
            if ($end_survey_redirect_url != "") {
                redirect($end_survey_redirect_url);
コード例 #4
0
ファイル: common.php プロジェクト: mypandos/REDCap-AutoNotify
 public function testLogic($logic)
 {
     logIt('testLogic: ' . $logic);
     if (LogicTester::isValid($logic)) {
         // Append current event details
         if (REDCap::isLongitudinal() && $this->redcap_event_name) {
             $logic = LogicTester::logicPrependEventName($logic, $this->redcap_event_name);
         }
         // Test logic
         logIt('Logic:' . $logic, 'DEBUG');
         if (LogicTester::evaluateLogicSingleRecord($logic, $this->record)) {
             $result = RCView::img(array('class' => 'imgfix', 'src' => 'accept.png')) . " True";
         } else {
             $result = RCView::img(array('class' => 'imgfix', 'src' => 'cross.png')) . " False";
         }
     } else {
         $result = RCView::img(array('class' => 'imgfix', 'src' => 'error.png')) . " Invalid Syntax";
     }
     return $result;
 }
コード例 #5
0
 public static function doReport($report_id = '0', $outputType = 'report', $outputFormat = 'html', $apiExportLabels = false, $apiExportHeadersAsLabels = false, $outputDags = false, $outputSurveyFields = false, $removeIdentifierFields = false, $hashRecordID = false, $removeUnvalidatedTextFields = false, $removeNotesFields = false, $removeDateFields = false, $dateShiftDates = false, $dateShiftSurveyTimestamps = false, $selectedInstruments = array(), $selectedEvents = array(), $returnIncludeRecordEventArray = false, $outputCheckboxLabel = false)
 {
     global $Proj, $user_rights, $isAjax, $app_title, $lang, $redcap_version;
     // Check report_id
     if (!is_numeric($report_id) && $report_id != 'ALL' && $report_id != 'SELECTED') {
         exit($isAjax ? '0' : 'ERROR');
     }
     // Increase memory limit in case needed for intensive processing
     if (str_replace("M", "", ini_get('memory_limit')) < 1024) {
         ini_set('memory_limit', '1024M');
     }
     // TESTING
     // if (isDev()) ini_set('memory_limit', '12M');
     // Determine if this is API report export
     $isAPI = PAGE == 'api/index.php' || PAGE == 'API/index.php';
     // Set flag to ALWAYS archive exported files in File Repository
     $archiveFiles = true;
     // Get report attributes
     $report = self::getReports($report_id, $selectedInstruments, $selectedEvents);
     if (empty($report)) {
         if ($isAPI) {
             exit(RestUtility::sendResponse(400, 'The value of the parameter "report_id" is not valid'));
         } else {
             exit($isAjax ? '0' : 'ERROR');
         }
     }
     // Check user rights: Does user have access to this report? (exclude super users in this check)
     if (defined('SUPER_USER') && !SUPER_USER || !defined('SUPER_USER')) {
         // If user has Add/Edit Report rights then let them view this report, OR if they have explicit rights to this report
         if (self::getReportNames($report_id, !$user_rights['reports']) == null) {
             // User does NOT have access to this report AND also does not have Add/Edit Report rights
             if ($isAPI) {
                 exit(RestUtility::sendResponse(403, "User \"" . USERID . "\" does not have access to this report."));
             } else {
                 exit($isAjax ? '0' : 'ERROR');
             }
         }
     }
     // Determine if a report or an export
     $outputType = $outputType == 'report' ? 'report' : 'export';
     if ($outputType != 'report') {
         $returnIncludeRecordEventArray = false;
     }
     // Determine whether to output a stats syntax file
     $stats_packages = array('r', 'spss', 'stata', 'sas');
     //		$outputSyntaxFile = (in_array($outputFormat, $stats_packages));
     // If CSV, determine whether to output a stats syntax file
     $outputAsLabels = $outputFormat == 'csvlabels';
     $outputHeadersAsLabels = $outputFormat == 'csvlabels';
     // List of fields to export
     $fields = $report['fields'];
     // If removing any fields due to DE-IDENTIFICATION, loop through them and remove them
     if ($removeIdentifierFields || $removeUnvalidatedTextFields || $removeNotesFields || $removeDateFields) {
         foreach ($fields as $key => $this_event_field) {
             $this_field = self::getFieldFromEventField($this_event_field);
             // Skip record ID field
             if ($this_field == $Proj->table_pk) {
                 continue;
             }
             // Get field type and validation type
             $this_field_type = $Proj->metadata[$this_field]['element_type'];
             $this_val_type = $Proj->metadata[$this_field]['element_validation_type'];
             $this_phi = $Proj->metadata[$this_field]['field_phi'];
             // Check if needs to be removed
             if ($this_phi && $removeIdentifierFields || $this_field_type == 'text' && $this_val_type == '' && $removeUnvalidatedTextFields || $this_field_type == 'textarea' && $removeNotesFields || $this_field_type == 'text' && $removeDateFields && substr($this_val_type, 0, 4) == 'date') {
                 // Remove the field from $fields
                 unset($fields[$key]);
             }
         }
     }
     // List of events to export
     $events = $report['limiter_events'];
     // Limit to user's DAG (if user is in a DAG), and if not in a DAG, then limit to the DAG filter
     $userInDAG = isset($user_rights['group_id']) && is_numeric($user_rights['group_id']);
     $dags = $userInDAG ? $user_rights['group_id'] : $report['filter_dags'];
     // Set options to include DAG names and/or survey fields (exclude ALL and SELECTED pre-defined reports)
     if (is_numeric($report_id)) {
         $outputDags = $report['output_dags'] == '1';
         $outputSurveyFields = $report['output_survey_fields'] == '1';
     } elseif (!is_numeric($report_id) && $outputType == 'report') {
         $outputDags = $outputSurveyFields = true;
     }
     // If user is in a DAG, then do not output the DAG name field
     if ($userInDAG) {
         $outputDags = false;
     }
     // If we're removing identifier fields, then also remove Survey Identifier (if outputting survey fields)
     $outputSurveyIdentifier = $outputSurveyFields && !$removeIdentifierFields;
     $outputScheduleDates = $report['output_schedule_dates'];
     $outputSurveyUrls = $report['output_survey_urls'];
     // File names for archived file
     $today_hm = date("Y-m-d_Hi");
     $projTitleShort = substr(str_replace(" ", "", ucwords(preg_replace("/[^a-zA-Z0-9 ]/", "", html_entity_decode($app_title, ENT_QUOTES)))), 0, 20);
     if ($outputFormat == 'r' || $outputFormat == 'csvraw') {
         // CSV with header row
         $csv_filename = $projTitleShort . "_DATA_" . $today_hm . ".csv";
     } elseif ($outputFormat == 'csvlabels') {
         // CSV labels
         $csv_filename = $projTitleShort . "_DATA_LABELS_" . $today_hm . ".csv";
     } else {
         // CSV without header row
         $csv_filename = $projTitleShort . "_DATA_NOHDRS_" . $today_hm . ".csv";
     }
     // Build sort array of sort fields and their attribute (ASC, DESC)
     $sortArray = array();
     if ($report['orderby_field1'] != '') {
         $sortArray[$report['orderby_field1']] = $report['orderby_sort1'];
     }
     if ($report['orderby_field2'] != '') {
         $sortArray[$report['orderby_field2']] = $report['orderby_sort2'];
     }
     if ($report['orderby_field3'] != '') {
         $sortArray[$report['orderby_field3']] = $report['orderby_sort3'];
     }
     // If the only sort field is record ID field, then remove it (because it will sort by record ID and event on its own)
     if (count($sortArray) == 1 && isset($sortArray[$Proj->table_pk]) && $sortArray[$Proj->table_pk] == 'ASC') {
         unset($sortArray[$Proj->table_pk]);
     }
     ## BUILD AND STORE CSV FILE
     // Set output format (CSV or HTML or API format)
     if ($isAPI) {
         // For API report export, return in desired format
         $returnDataFormat = $outputFormat;
         $outputAsLabels = $apiExportLabels;
         $outputHeadersAsLabels = $apiExportHeadersAsLabels;
     } elseif ($outputType == 'report') {
         // For webpage report, return html
         $returnDataFormat = 'html';
     } else {
         $returnDataFormat = 'csv';
     }
     // Check syntax of logic string: If there is an issue in the logic, then return false and stop processing
     if ($outputType == 'report' && $report['limiter_logic'] != '' && !LogicTester::isValid($report['limiter_logic'])) {
         return array(RCView::div(array('class' => 'red'), RCView::img(array('src' => 'exclamation.png', 'class' => 'imgfix')) . RCView::b($lang['global_01'] . $lang['colon']) . " " . $lang['report_builder_132']), 0);
     }
     // Retrieve CSV data file
     $data_content = LongitudinalRecords::getData(PROJECT_ID, $returnDataFormat, array(), $fields, $events, $dags, false, $outputDags, $outputSurveyFields, $report['limiter_logic'], $outputAsLabels, $outputHeadersAsLabels, $hashRecordID, $dateShiftDates, $dateShiftSurveyTimestamps, $sortArray, $outputType != 'report', true, $returnIncludeRecordEventArray, true, $outputSurveyIdentifier, $outputCheckboxLabel, $outputScheduleDates, $outputSurveyUrls);
     // Replace any MS Word chacters in the data (from 6.12.0 string passed by ref)
     if (version_compare($redcap_version, '6.12.0', '<')) {
         $data_content = replaceMSchars($data_content);
     } else {
         //replaceMSchars(is_array($data_content) ? $data_content[0] : $data_content); //"Only variables can be passed by reference"
         if (is_array($data_content)) {
             replaceMSchars($data_content[0]);
         } else {
             replaceMSchars($data_content);
         }
     }
     ## Logging (for exports only)
     if ($outputType != 'report' || $isAPI) {
         // Set data_values as JSON-encoded
         $data_values = array('report_id' => $report_id, 'export_format' => substr($outputFormat, 0, 3) == 'csv' ? 'CSV' : strtoupper($outputFormat), 'rawOrLabel' => $outputAsLabels ? 'label' : 'raw');
         if ($outputDags) {
             $data_values['export_data_access_group'] = 'Yes';
         }
         if ($outputSurveyFields) {
             $data_values['export_survey_fields'] = 'Yes';
         }
         if ($dateShiftDates) {
             $data_values['date_shifted'] = 'Yes';
         }
         if (isset($user_rights['data_export_tool']) && $user_rights['data_export_tool'] == '2') {
             $data_values['deidentified'] = 'Yes';
         }
         if (isset($user_rights['data_export_tool']) && $user_rights['data_export_tool'] == '3') {
             $data_values['removed_identifiers'] = 'Yes';
         }
         $data_values['fields'] = empty($fields) ? array_keys($Proj->metadata) : $fields;
         // Log it
         log_event("", "redcap_data", "longitudinal_report", "", json_encode($data_values), "Longitudinal Report" . ($isAPI ? " (API)" : ""));
     }
     // IF OUTPUTTING A REPORT, RETURN THE CONTENT HERE
     if ($outputType == 'report' || $isAPI) {
         return $data_content;
     }
     // For SAS, SPSS, and Stata, remove the CSV file's header row
     if (in_array($outputFormat, array('spss', 'stata', 'sas'))) {
         // Remove header row
         list($headers, $data_content) = explode("\n", $data_content, 2);
     }
     // Store the data file
     $data_edoc_id = self::storeExportFile($csv_filename, $data_content, $archiveFiles, $dateShiftDates);
     if ($data_edoc_id === false) {
         return false;
     }
     /* Stats syntax not implemented for Longitudinal Reports		
     		## BUILD AND STORE SYNTAX FILE (if applicable)
     		// If exporting to a stats package, then also generate the associate syntax file for that package
     		$syntax_edoc_id = null;
     		if ($outputSyntaxFile) {
     			// Generate syntax file	
     			$syntax_file_contents = self::getStatsPackageSyntax($outputFormat, $fields, $csv_filename, $outputDags, $outputSurveyFields, $removeIdentifierFields);
     			// Set the filename of the syntax file
     			if ($outputFormat == 'spss') {
     				$stats_package_filename = $projTitleShort ."_" . strtoupper($outputFormat) . "_$today_hm.sps";
     			} elseif ($outputFormat == 'stata') {
     				$stats_package_filename = $projTitleShort ."_" . strtoupper($outputFormat) . "_$today_hm.do";
     			} else {
     				$stats_package_filename = $projTitleShort ."_" . strtoupper($outputFormat) . "_$today_hm.$outputFormat";
     			}
     			// Store the syntax file
     			$syntax_edoc_id = self::storeExportFile($stats_package_filename, $syntax_file_contents, $archiveFiles, $dateShiftDates);
     			if ($syntax_edoc_id === false) return false;
     		}	
     */
     $syntax_edoc_id = null;
     // Return the edoc_id's of the CSV data file
     return array($data_edoc_id, $syntax_edoc_id);
 }