Skip to content

Instantly share code, notes, and snippets.

@bronius
Last active June 25, 2018 19:18
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save bronius/92393784768bc531eca95fb55f68d3d2 to your computer and use it in GitHub Desktop.
Save bronius/92393784768bc531eca95fb55f68d3d2 to your computer and use it in GitHub Desktop.
Super fast replacement for field_encrypt_views_query_alter in contrib module https://www.drupal.org/project/field_encrypt_views_filters
<?php
// The original project query_alter takes each encrypted field with a value sought out of the query
// Executes a query of all other fields (or none if none)
// Creates a MySQL temporary table and populates with decrypted fields' values
// Adds that temp table as a join on the original View
// And then executes the view, letting MySQL query against that temporary table of decrypted values.
//
// This approach expects a parallel field, field_name_md5, to contain an md5 hash of the original,
// decrypted value (CRUD updated with entity/node hooks or as calculated field). At query execution,
// all encrypted field and filter values are swapped out for md5-equiv and md5 of the filter value,
// and BAM it's lightning fast.
function field_encrypt_views_filters_views_query_alter(&$view, &$query) {
// Check for encrypted fields in the filters.
$encrypted_filter_fields = _field_encrypt_views_filters_get_encrypted_filters($view, $query);
if (empty($encrypted_filter_fields)) {
return;
}
$encrypted_query_filters = array();
foreach($encrypted_filter_fields as $field_name) {
$encrypted_query_filters[$field_name] = $view->exposed_raw_input[$field_name . '_value'];
}
// dpm($encrypted_query_filters, 'encrypted fields');
$encrypted_field_columns = _field_encrypt_views_filters_get_encrypted_columns($view);
// dpm($encrypted_field_columns, 'efcolumns');
// Change the query so that no encrypted fields are in the filters.
foreach ($query->where as $group => $where) {
foreach ($where['conditions'] as $index => $condition) {
if (isset($condition['field'])) {
if (is_string($condition['field']) && in_array($condition['field'], $encrypted_field_columns)) {
// Rewrite the where clause with the parallel md5 equivalent field table, column name and md5 hash value.
$field_col_name_parts = explode('.', $query->where[$group]['conditions'][$index]['field']);
$field_col_name_part_value = substr($field_col_name_parts[1], 0, -6) . '_md5_value';
$table_name_md5 = $field_col_name_parts[0] . '_md5';
$query->where[$group]['conditions'][$index]['field'] = $table_name_md5 . '.' . $field_col_name_part_value;
$query->where[$group]['conditions'][$index]['value'] = md5($query->where[$group]['conditions'][$index]['value']);
// Join the temporary table to the views query.
$join = new views_join();
$join->left_table = $view->base_table;
$join->left_field = $view->base_field;
$join->table = $table_name_md5;
$join->field = 'entity_id';
$join->type = 'LEFT';
$query->table_queue[$table_name_md5] = array(
'alias' => $table_name_md5,
'table' => $table_name_md5,
'relationship' => 'node',
'join' => $join,
);
}
// BRONIUS: not analyzed
elseif (is_string($condition['field']) && _field_encrypt_views_filters_combined_field_query($view, $condition['field'], 'match')) {
unset($query->where[$group]['conditions'][$index]);
}
// BRONIUS: not analyzed
elseif ($condition['field'] instanceof DatabaseCondition && _field_encrypt_views_filters_combined_field_database_condition($view, $condition['field'], 'match')) {
unset($query->where[$group]['conditions'][$index]);
}
}
}
}
// dpm($query->where, 'query where');
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment