modules/custom/deims_variable_search/deims_variable_search.module
<?php
/**
* Implements hook_menu().
*/
function deims_variable_search_menu() {
$info = array();
$info['deims-variable-search/autocomplete/%/%'] = array(
'page callback' => 'deims_variable_search_autocomplete',
'page arguments' => array(2, 3),
'access callback' => 'deims_variable_search_autocomplete_access',
'access arguments' => array(2, 3),
'type' => MENU_CALLBACK,
'file' => 'deims_variable_search.pages.inc',
);
return $info;
}
/**
* Access callback for accessing the variable search results.
*/
function deims_variable_search_autocomplete_access($field_name, $entity_type) {
$field = field_info_field($field_name);
return !empty($field) && $field['storage']['type'] == 'field_sql_storage' && field_access('edit', $field, $entity_type) && field_has_data($field_name);
}
/**
* Implements hook_cron().
*
* Perform indexing on variables that have not been indexed, or have been
* requested to re-index.
*/
function deims_variable_search_cron() {
$limit = (int) variable_get('deims_variable_search_cron_limit', 100);
$fields = deims_variable_get_variable_fields();
foreach ($fields as $field_name => $field) {
$table = db_escape_table(_field_sql_storage_tablename($field));
$id_column = db_escape_field(_field_sql_storage_columnname($field_name, 'id'));
$sql = "SELECT v.$id_column FROM {" . $table . "} v LEFT JOIN search_dataset d ON d.type = :field_name AND d.sid = v.$id_column WHERE v.deleted = 0 AND (d.sid IS NULL OR d.reindex <> 0) ORDER BY d.reindex ASC, v.$id_column ASC";
if ($ids = db_query_range($sql, 0, $limit, array(':field_name' => $field_name), array('target' => 'slave'))->fetchCol()) {
if ($items = deims_variable_load_multiple($field_name, $ids)) {
deims_variable_search_index_variables($field_name, $items);
}
}
}
}
/**
* Implements hook_field_attach_submit().
*/
function deims_variable_search_field_attach_submit($entity_type, $entity, $form, &$form_state) {
// Because this field is invoked when an entity is submitted via a form, we
// can set an internal indicator that we can index the variable fields on
// this entity on the same request.
$entity->deims_variable_search_can_index = variable_get('deims_variable_search_index_immediately', TRUE);
}
/**
* Implements hook_field_attach_insert().
*/
function deims_variable_search_field_attach_insert($entity_type, $entity) {
list(, , $bundle) = entity_extract_ids($entity_type, $entity);
$instances = array_intersect_key(field_info_instances($entity_type, $bundle), deims_variable_get_variable_fields());
foreach ($instances as $field_name => $instance) {
if (!empty($entity->deims_variable_search_can_index) && $items = field_get_items($entity_type, $entity, $field_name)) {
drupal_register_shutdown_function('deims_variable_search_index_variables', $field_name, $items);
drupal_register_shutdown_function('search_update_totals');
}
}
}
/**
* Implements hook_field_attach_update().
*/
function deims_variable_search_field_attach_update($entity_type, $entity) {
list(, , $bundle) = entity_extract_ids($entity_type, $entity);
$instances = array_intersect_key(field_info_instances($entity_type, $bundle), deims_variable_get_variable_fields());
foreach ($instances as $field_name => $instance) {
// Because some variables may have been removed, we should just clear out
// the original items in the search index, and then re-index the new items.
if ($original_items = field_get_items($entity_type, $entity->original, $field_name)) {
deims_variable_search_delete_variables($field_name, $original_items);
}
if (!empty($entity->deims_variable_search_can_index) && $items = field_get_items($entity_type, $entity, $field_name)) {
drupal_register_shutdown_function('deims_variable_search_index_variables', $field_name, $items);
drupal_register_shutdown_function('search_update_totals');
}
}
}
/**
* Implements hook_field_attach_delete().
*/
function deims_variable_search_field_attach_delete($entity_type, $entity) {
list(, , $bundle) = entity_extract_ids($entity_type, $entity);
$instances = array_intersect_key(field_info_instances($entity_type, $bundle), deims_variable_get_variable_fields());
foreach ($instances as $field_name => $instance) {
if ($items = field_get_items($entity_type, $entity, $field_name)) {
deims_variable_search_delete_variables($field_name, $items);
}
}
}
/**
* Implements hook_field_widget_WIDGET_TYPE_form_alter().
*/
function deims_variable_search_field_widget_deims_variable_default_form_alter(&$element, &$form_state, $context) {
$item = isset($context['items'][$context['delta']]) ? $context['items'][$context['delta']] : array();
//$element['actions']['search'] = array(
// '#type' => 'button',
// '#value' => t('Clone existing variable'),
// '#execute_submit_handlers' => FALSE,
// '#limit_validation_errors' => array(),
// '#weight' => -10,
//);
$search_uri = array(
'path' => 'deims-variable-search/autocomplete/' . $context['field']['field_name'] . '/' . $context['instance']['entity_type'],
'options' => array(),
);
if (!empty($item['id'])) {
$search_uri['options']['query']['exclude-variable-id'] = $item['id'];
}
$element['search'] = array(
'#type' => 'searchfield',
'#title' => t('Search existing variables'),
'#title_display' => 'invisible',
'#attributes' => array(
'class' => array('deims-variable-search-autocomplete'),
'data-source' => url($search_uri['path'], $search_uri['options']),
'data-form-parent' => $element['#state_parent'],
'placeholder' => t('Re-use an existing variable'),
),
'#access' => deims_variable_search_autocomplete_access($context['field']['field_name'], $context['instance']['entity_type']),
'#input' => FALSE,
'#attached' => array(
'library' => array(
array('system', 'ui.autocomplete'),
),
'js' => array(
drupal_get_path('module', 'deims_variable_search') . '/js/field.js',
),
),
'#weight' => -150,
);
}
function deims_variable_load_multiple($field_name, array $ids) {
$field = field_info_field($field_name);
if ($field['storage']['type'] != 'field_sql_storage') {
throw new DomainException('Cannot load DEIMS variables for field ' . $field_name . ' because it does not use SQL storage.');
}
if (empty($ids)) {
return array();
}
$items = array();
$table = db_escape_table(_field_sql_storage_tablename($field));
$id_column = db_escape_field(_field_sql_storage_columnname($field_name, 'id'));
$results = db_query("SELECT * FROM {" . $table . "} WHERE $id_column IN (:ids) AND deleted = 0", array(':ids' => $ids));
foreach ($results as $row) {
$item = array();
foreach ($field['columns'] as $column => $attributes) {
$column_name = _field_sql_storage_columnname($field_name, $column);
$item[$column] = $row->$column_name;
}
// @todo Unseralize item values? Possibly by somehow running through deims_variable_field_load()?
$item['data'] = unserialize($item['data']);
$item['missing_values'] = unserialize($item['missing_values']);
$items[$item['id']] = $item;
}
return $items;
}
/**
* Return an array of variable fields, keyed by field name.
*/
function deims_variable_get_variable_fields() {
$fields = array();
foreach (field_info_field_map() as $field_name => $field) {
if ($field['type'] == 'deims_variable') {
$info = field_info_field($field_name);
if ($info['storage']['type'] == 'field_sql_storage') {
$fields[$field_name] = $info;
}
}
}
return $fields;
}
/**
* Add variables to the search index.
*/
function deims_variable_search_index_variables($field_name, array $items) {
foreach ($items as $item) {
$text = '<h1>' . $item['name'] . '</h1>';
$text .= '<h2>' . $item['label'] . '</h2>';
$text .= '<h3>' . $item['definition'] . '</h3>';
search_index($item['id'], $field_name, $text);
}
}
/**
* Set variables as needing a reindex on the next cron run.
*/
function deims_variable_search_reindex_variables($field_name, array $items) {
if ($ids = ArrayHelper::extractNestedValuesToArray($items, array('id'))) {
db_update('search_dataset')
->fields(array('reindex' => REQUEST_TIME))
->condition('type', $field_name)
->condition('sid', $ids, 'IN')
->execute();
}
}
/**
* Remove variables from the search index.
*/
function deims_variable_search_delete_variables($field_name, array $items) {
if ($ids = ArrayHelper::extractNestedValuesToArray($items, array('id'))) {
foreach ($ids as $id) {
search_reindex($id, $field_name);
}
drupal_register_shutdown_function('search_update_totals');
}
}