You are here

wsfields_storage.module in Web Service Data 7

Storage controller definitions

@author Mathew Winstone <mwinstone@coldfrontlabs.ca> @author David Pascoe-Deslauriers <dpascoed@coldfrontlabs.ca>

File

modules/wsfields_storage/wsfields_storage.module
View source
<?php

/**
 * @file
 * Storage controller definitions
 *
 * @author Mathew Winstone <mwinstone@coldfrontlabs.ca>
 * @author David Pascoe-Deslauriers <dpascoed@coldfrontlabs.ca>
 */

/**
 *  Implements hook_menu().
 */
function wsfields_storage_menu() {
  $items = array();
  $items['admin/config/services/wsfields_storage'] = array(
    'title' => t('WSField Storage Fields and Settings'),
    'description' => t('Configure wsfield fields.'),
    'page callback' => 'drupal_get_form',
    'page arguments' => array(
      'wsfields_storage_settings_form',
    ),
    'file' => 'wsfields_storage.admin.inc',
    'access callback' => 'user_access',
    'access arguments' => array(
      'administer wsfields',
    ),
  );
  $items['admin/config/services/wsfields_storage/edit'] = array(
    'title' => t('WSField Storage Fields and Settings'),
    'description' => t('Configure wsfield fields.'),
    'page callback' => 'drupal_get_form',
    'page arguments' => array(
      'wsfields_storage_edit_field_form',
    ),
    'file' => 'wsfields_storage.admin.inc',
    'type' => MENU_CALLBACK,
    'access callback' => 'user_access',
    'access arguments' => array(
      'administer wsfields',
    ),
  );
  $items['admin/config/services/wsfields_storage/delete'] = array(
    'title' => t('WSField Storage Fields and Settings'),
    'description' => t('Configure wsfield fields.'),
    'page callback' => 'drupal_get_form',
    'page arguments' => array(
      'wsfields_storage_delete_field_form',
    ),
    'file' => 'wsfields_storage.admin.inc',
    'type' => MENU_CALLBACK,
    'access callback' => 'user_access',
    'access arguments' => array(
      'administer wsfields',
    ),
  );
  return $items;
}

/**
 * Returns whether the entity_type has a wsfield attached to it
 * and cache the result
 */
function wsfields_storage_entity_has_wsfields($entity_type) {
  $ret = cache_get('wsfields_storage_entity_has_wsfields:' . $entity_type, 'cache');
  if (!$ret) {
    $ret = _wsfields_storage_entity_has_wsfields($entity_type);
    cache_set('wsfields_storage_entity_has_wsfields:' . $entity_type, $ret, 'cache');
  }
  else {
    $ret = $ret->data;
  }
  return $ret;
}

/**
 * Returns whether the entity_type has a wsfield attached to it
 */
function _wsfields_storage_entity_has_wsfields($entity_type) {
  $fields = field_info_fields();
  $wsfields = array();
  foreach ($fields as $key => $field) {
    if ($field['storage']['type'] == 'wsfields_storage') {
      $wsfields[$key] = $field;
    }
  }
  $instances = field_info_instances($entity_type);
  foreach ($instances as $instance) {
    foreach ($instance as $field) {
      if (isset($wsfields[$field['field_name']])) {
        return TRUE;
      }
    }
  }
  return FALSE;
}

/**
 * Implements hook_field_storage_info().
 *
 * The settings array stores the machine name of a wsconfig instance to load.
 */
function wsfields_storage_field_storage_info() {
  return array(
    'wsfields_storage' => array(
      'label' => t('Web Service Storage'),
      'description' => t('Stores fields via remote web service using REST.'),
      'settings' => array(
        'wsconfig_name' => '',
        // The machine-name of a wsconfig instance to load
        'translation' => FALSE,
        'propertymap' => array(
          'create' => array(),
          'read' => array(),
          'update' => array(),
          'delete' => array(),
        ),
        // Mapping of the placeholder elements in the CRUD paths to entity properties
        'processor' => '',
        // Data processor
        'remotekey' => '',
      ),
    ),
  );
}

/**
 * Implements hook_field_storage_details().
 */
function wsfields_storage_field_storage_details($field) {

  // Nothing right now
  // @todo something
}

/**
 * Implements hook_field_storage_create_field().
 */
function wsfields_storage_field_storage_create_field($field) {

  // Act on when a new field is created
  cache_clear_all('wsfields_storage_entity_has_wsfields:*', 'cache', TRUE);
}

/**
 * Implements hook_field_storage_update_field().
 */
function wsfields_storage_field_storage_update_field($field, $prior_field, $has_data) {
  cache_clear_all('wsfields_storage_entity_has_wsfields:*', 'cache', TRUE);
}

/**
 * Implements hook_field_storage_delete_field().
 */
function wsfields_storage_field_storage_delete_field($field) {
  cache_clear_all('wsfields_storage_entity_has_wsfields:*', 'cache', TRUE);
}

/**
 * Implements hook_field_storage_delete().
 */
function wsfields_storage_field_storage_delete($entity_type, $entity, $fields) {

  // @todo something
}

/**
 * Implements hook_field_storage_delete_revision().
 */
function wsfields_storage_field_storage_delete_revision($entity_type, $entity, $fields) {

  // @todo something
}

/**
 * Implements hook_field_storage_delete_instance().
 */
function wsfields_storage_field_storage_delete_instance($instance) {
  cache_clear_all('wsfields_storage_entity_has_wsfields:*', 'cache', TRUE);
}

/**
 * Implements hook_field_storage_load().
 */
function wsfields_storage_field_storage_load($entity_type, $entities, $age, $fields, $options) {

  // Load the list of fields
  $field_info = field_info_field_by_ids();
  $load_current = $age == FIELD_LOAD_CURRENT;

  // Loop through the fields
  foreach ($fields as $field_id => $ids) {
    $field = $field_info[$field_id];
    $field_name = $field['field_name'];

    // Load the data for each entity
    foreach ($entities as $entityid => $entity) {

      // Load the field data into the entity
      $entities[$entityid]->{$field_name} = wsfields_data_load($entity_type, $field, $entity);
    }
  }
}

/**
 * Implements hook_field_storage_write().
 */
function wsfields_storage_field_storage_write($entity_type, $entity, $op, $fields) {
  foreach ($fields as $field_id) {
    $field = field_info_field_by_id($field_id);
    $field_name = $field['field_name'];
    $all_languages = field_available_languages($entity_type, $field);
    $field_languages = array_intersect($all_languages, array_keys((array) $entity->{$field_name}));
    foreach ($field_languages as $langcode) {
      $items = (array) $entity->{$field_name}[$langcode];
      $delta_count = 0;

      // Trim the list of items down to what the field has been set to
      if ($field['cardinality'] != FIELD_CARDINALITY_UNLIMITED and count($items) > $field['cardinality']) {
        $items = array_chunk($items, count($items), TRUE);
        $items = reset($items);
      }
      wsfields_data_write($entity_type, $entity, $op, $field, $items);
    }
  }
}

/**
 * Implements hook_field_storage_query().
 */
function wsfields_storage_field_storage_query($query) {
  $groups = array();
  if ($query->age == FIELD_LOAD_CURRENT) {
    $id_key = 'entity_id';
  }
  else {
    $id_key = 'revision_id';
  }

  // Add wsconfigs required for the fields used.
  // @todo
  // Original sql based code

  /*
    $table_aliases = array();
    // Add tables for the fields used.
    foreach ($query->fields as $key => $field) {
      $tablename = $tablename_function($field);
      // Every field needs a new table.
      $table_alias = $tablename . $key;
      $table_aliases[$key] = $table_alias;
      if ($key) {
        $select_query->join($tablename, $table_alias, "$table_alias.entity_type = $field_base_table.entity_type AND $table_alias.$id_key = $field_base_table.$id_key");
      }
      else {
        $select_query = db_select($tablename, $table_alias);
        $select_query->addTag('entity_field_access');
        $select_query->addMetaData('base_table', $tablename);
        $select_query->fields($table_alias, array('entity_type', 'entity_id', 'revision_id', 'bundle'));
        $field_base_table = $table_alias;
      }
      if ($field['cardinality'] != 1) {
        $select_query->distinct();
      }
    }


    // Add field conditions.
    foreach ($query->fieldConditions as $key => $condition) {
      // Throw an exception for each field condition which isn't supported
      throw new WSFieldsStorageUnsupportedFieldConditionException('Field condition is unsupported.');

      // Original sql based code
      /*
      $table_alias = $table_aliases[$key];
      $field = $condition['field'];
      // Add the specified condition.
      $sql_field = "$table_alias." . _field_sql_storage_columnname($field['field_name'], $condition['column']);
      $query->addCondition($select_query, $sql_field, $condition);
      // Add delta / language group conditions.
      foreach (array('delta', 'language') as $column) {
        if (isset($condition[$column . '_group'])) {
          $group_name = $condition[$column . '_group'];
          if (!isset($groups[$column][$group_name])) {
            $groups[$column][$group_name] = $table_alias;
          }
          else {
            $select_query->where("$table_alias.$column = " . $groups[$column][$group_name] . ".$column");
          }
        }
      }

    }

    // Look in list of deleted fields
    // @todo is this supported with web services?
    if (isset($query->deleted)) {
      $select_query->condition("$field_base_table.deleted", (int) $query->deleted);
    }

    // Is there a need to sort the query by property?
    $has_property_order = FALSE;
    foreach ($query->order as $order) {
      if ($order['type'] == 'property') {
        $has_property_order = TRUE;
      }
    }

    // Check for property conditions
    if ($query->propertyConditions || $has_property_order) {
      if (empty($query->entityConditions['entity_type']['value'])) {
        throw new EntityFieldQueryException('Property conditions and orders must have an entity type defined.');
      }
      $entity_type = $query->entityConditions['entity_type']['value'];
      $entity_base_table = _field_sql_storage_query_join_entity($select_query, $entity_type, $field_base_table);
      $query->entityConditions['entity_type']['operator'] = '=';
      foreach ($query->propertyConditions as $property_condition) {
        $query->addCondition($select_query, "$entity_base_table." . $property_condition['column'], $property_condition);
      }
    }
    foreach ($query->entityConditions as $key => $condition) {
      $query->addCondition($select_query, "$field_base_table.$key", $condition);
    }

    // Order the query.
    foreach ($query->order as $order) {
      if ($order['type'] == 'entity') {
        $key = $order['specifier'];
        $select_query->orderBy("$field_base_table.$key", $order['direction']);
      }
      elseif ($order['type'] == 'field') {
        $specifier = $order['specifier'];
        $field = $specifier['field'];
        $table_alias = $table_aliases[$specifier['index']];
        $sql_field = "$table_alias." . _field_sql_storage_columnname($field['field_name'], $specifier['column']);
        $select_query->orderBy($sql_field, $order['direction']);
      }
      elseif ($order['type'] == 'property') {
        $select_query->orderBy("$entity_base_table." . $order['specifier'], $order['direction']);
      }
    }

    return $query->finishQuery($select_query, $id_key);*/
}

/**
 * Implements hook_entity_query_alter().
 */
function wsfields_storage_entity_query_alter($query) {

  // @todo ensure the alter only occurs for entities which have
  // web service fields

  //$query->executeCallback = 'wsfields_storage_field_storage_query';
}

/**
 * Implements hook_field_attach_rename_bundle().
 */
function wsfields_storage_field_attach_rename_bundle($entity_type, $bundle_old, $bundle_new) {

  // @todo something
}

/**
 * Implements hook_entity_insert().
 */
function wsfields_storage_entity_insert($entity, $entity_type) {
  wsfields_storage_field_storage_write($entity_type, $entity, NULL, array(), TRUE);
}

/**
 * Implements hook_entity_update().
 */
function wsfields_storage_entity_update($entity, $entity_type) {
  wsfields_storage_field_storage_write($entity_type, $entity, NULL, array(), TRUE);
}

/**
 * Implements hook_field_attach_delete().
 */
function wsfields_storage_field_attach_delete($entity_type, $entity) {

  // @todo something
}

/**
 * Implements hook_entity_info_alter().
 */
function wsfields_storage_entity_info_alter(&$entity_info) {

  // @todo something

  //dpm($entity_info);
}

/**
 * Maps the field data to their defined column values
 *
 * @param array $field
 *  Field info
 * @param array $instance_settings
 *  Field instance settings
 * @return array|boolean
 *  Returns an array of mapped data, FALSE otherwise.
 */
function _wsfields_storage_columnname($field, $instance_settings) {

  // @todo have the wsconfig or parser or something include a map to the field schema names
}

/**
 * Exception handling for WS Field Storage
 */
class WSFieldsStorageException extends Exception {

}
class WSFieldsStorageUnsupportedFieldConditionException extends WSFieldsStorageException {

}
class WSFieldsStorageUnsupportedQueryException extends WSFieldsStorageException {

}

/**
 * Debug query
 */
function _wsfields_storage_test_query() {
  try {
    $query = new EntityFieldQuery();
    $query
      ->entityCondition('entity_type', 'user')
      ->entityCondition('bundler', 'user')
      ->fieldCondition('uo_user_surname', 'value', 'phehibrufri', '=');
    $query
      ->execute();
  } catch (WSFieldsStorageException $e) {
    dpm($e
      ->getMessage());
  }
}

Functions

Namesort descending Description
wsfields_storage_entity_has_wsfields Returns whether the entity_type has a wsfield attached to it and cache the result
wsfields_storage_entity_info_alter Implements hook_entity_info_alter().
wsfields_storage_entity_insert Implements hook_entity_insert().
wsfields_storage_entity_query_alter Implements hook_entity_query_alter().
wsfields_storage_entity_update Implements hook_entity_update().
wsfields_storage_field_attach_delete Implements hook_field_attach_delete().
wsfields_storage_field_attach_rename_bundle Implements hook_field_attach_rename_bundle().
wsfields_storage_field_storage_create_field Implements hook_field_storage_create_field().
wsfields_storage_field_storage_delete Implements hook_field_storage_delete().
wsfields_storage_field_storage_delete_field Implements hook_field_storage_delete_field().
wsfields_storage_field_storage_delete_instance Implements hook_field_storage_delete_instance().
wsfields_storage_field_storage_delete_revision Implements hook_field_storage_delete_revision().
wsfields_storage_field_storage_details Implements hook_field_storage_details().
wsfields_storage_field_storage_info Implements hook_field_storage_info().
wsfields_storage_field_storage_load Implements hook_field_storage_load().
wsfields_storage_field_storage_query Implements hook_field_storage_query().
wsfields_storage_field_storage_update_field Implements hook_field_storage_update_field().
wsfields_storage_field_storage_write Implements hook_field_storage_write().
wsfields_storage_menu Implements hook_menu().
_wsfields_storage_columnname Maps the field data to their defined column values
_wsfields_storage_entity_has_wsfields Returns whether the entity_type has a wsfield attached to it
_wsfields_storage_test_query Debug query

Classes