$timer['start_main'] = microtime(true);
//$empty_result = db_query("SELECT * FROM redcap_data WHERE project_id = '$project_id' AND value = '' ORDER BY abs(record) ASC");
	/**
	 * exclude dm_subjid from query, as RED-I writes orphan records to this field, and we don't want to screw that up, do we?
	 */
	$empty_result = db_query("SELECT * FROM redcap_data WHERE project_id = '$project_id' AND field_name = '{$_POST['field_name']}' ORDER BY abs(record) ASC");
	if ($empty_result) {
		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?');
			}
 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;
 }