field_test.module 10 KB
Newer Older
1 2
<?php

3 4
use Drupal\Core\Entity\EntityInterface;

5 6 7 8 9 10 11 12 13 14 15 16 17
/**
 * @file
 * Helper module for the Field API tests.
 *
 * The module defines
 * - an entity type (field_test.entity.inc)
 * - a field type and its formatters and widgets (field_test.field.inc)
 * - a field storage backend (field_test.storage.inc)
 *
 * The main field_test.module file implements generic hooks and provides some
 * test helper functions
 */

18 19 20
require_once DRUPAL_ROOT . '/core/modules/field/tests/modules/field_test/field_test.entity.inc';
require_once DRUPAL_ROOT . '/core/modules/field/tests/modules/field_test/field_test.field.inc';
require_once DRUPAL_ROOT . '/core/modules/field/tests/modules/field_test/field_test.storage.inc';
21 22 23 24 25 26 27 28 29 30

/**
 * Implements hook_permission().
 */
function field_test_permission() {
  $perms = array(
    'access field_test content' => array(
      'title' => t('Access field_test content'),
      'description' => t('View published field_test content.'),
    ),
31 32 33 34
    'view test_view_field content' => array(
      'title' => t('View test field content'),
      'description' => t('View published test_view_field content.'),
    ),
35 36 37 38 39 40 41 42 43 44 45 46 47 48
    'administer field_test content' => array(
      'title' => t('Administer field_test content'),
      'description' => t('Manage field_test content'),
    ),
  );
  return $perms;
}

/**
 * Implements hook_menu().
 */
function field_test_menu() {
  $items = array();

49
  foreach (entity_get_bundles('test_entity') as $bundle_name => $bundle_info) {
50
    $items['test-entity/add/' . $bundle_name] = array(
51 52 53 54 55 56 57
      'title' => t('Add %bundle test_entity', array('%bundle' => $bundle_info['label'])),
      'page callback' => 'field_test_entity_add',
      'page arguments' => array(2),
      'access arguments' => array('administer field_test content'),
      'type' => MENU_NORMAL_ITEM,
    );
  }
58
  $items['test-entity/manage/%field_test_entity_test/edit'] = array(
59 60
    'title' => 'Edit test entity',
    'page callback' => 'field_test_entity_edit',
61
    'page arguments' => array(2),
62 63 64 65
    'access arguments' => array('administer field_test content'),
    'type' => MENU_NORMAL_ITEM,
  );

66 67 68 69 70 71 72 73
  $items['test-entity/nested/%field_test_entity_test/%field_test_entity_test'] = array(
    'title' => 'Nested entity form',
    'page callback' => 'drupal_get_form',
    'page arguments' => array('field_test_entity_nested_form', 2, 3),
    'access arguments' => array('administer field_test content'),
    'type' => MENU_NORMAL_ITEM,
  );

74 75 76 77 78 79 80 81
  return $items;
}

/**
 * Generic op to test _field_invoke behavior.
 *
 * This simulates a field operation callback to be invoked by _field_invoke().
 */
82 83
function field_test_field_test_op(EntityInterface $entity, $field, $instance, $langcode, &$items) {
  return array($langcode => hash('sha256', serialize(array($entity, $field['field_name'], $langcode, $items))));
84 85 86 87 88 89 90 91
}

/**
 * Generic op to test _field_invoke_multiple behavior.
 *
 * This simulates a multiple field operation callback to be invoked by
 * _field_invoke_multiple().
 */
92
function field_test_field_test_op_multiple($entity_type, $entities, $field, $instances, $langcode, &$items) {
93
  $result = array();
94
  foreach ($entities as $id => $entity) {
95 96 97 98 99 100
    // Entities, instances and items are assumed to be consistently grouped by
    // language. To verify this we try to access all the passed data structures
    // by entity id. If they are grouped correctly, one entity, one instance and
    // one array of items should be available for each entity id.
    $field_name = $instances[$id]['field_name'];
    $result[$id] = array($langcode => hash('sha256', serialize(array($entity_type, $entity, $field_name, $langcode, $items[$id]))));
101 102 103 104 105
  }
  return $result;
}

/**
106
 * Implements hook_field_available_languages_alter().
107
 */
108
function field_test_field_available_languages_alter(&$langcodes, $context) {
109
  if (state()->get('field_test.field_available_languages_alter')) {
110 111 112 113 114
    // Add an unavailable language code.
    $langcodes[] = 'xx';
    // Remove an available language code.
    $index = array_search('en', $langcodes);
    unset($langcodes[$index]);
115 116 117 118
  }
}

/**
119
 * Implements hook_field_language_alter().
120
 */
121
function field_test_field_language_alter(&$display_langcode, $context) {
122
  if (state()->get('field_test.language_fallback') ?: TRUE) {
123
    field_language_fallback($display_langcode, $context['entity'], $context['langcode']);
124
  }
125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170
}

/**
 * Store and retrieve keyed data for later verification by unit tests.
 *
 * This function is a simple in-memory key-value store with the
 * distinction that it stores all values for a given key instead of
 * just the most recently set value. field_test module hooks call
 * this function to record their arguments, keyed by hook name. The
 * unit tests later call this function to verify that the correct
 * hooks were called and were passed the correct arguments.
 *
 * This function ignores all calls until the first time it is called
 * with $key of NULL. Each time it is called with $key of NULL, it
 * erases all previously stored data from its internal cache, but also
 * returns the previously stored data to the caller. A typical usage
 * scenario is:
 *
 * @code
 *   // calls to field_test_memorize() here are ignored
 *
 *   // turn on memorization
 *   field_test_memorize();
 *
 *   // call some Field API functions that invoke field_test hooks
 *   $field = field_create_field(...);
 *
 *   // retrieve and reset the memorized hook call data
 *   $mem = field_test_memorize();
 *
 *   // make sure hook_field_create_field() is invoked correctly
 *   assertEqual(count($mem['field_test_field_create_field']), 1);
 *   assertEqual($mem['field_test_field_create_field'][0], array($field));
 * @endcode
 *
 * @param $key
 *   The key under which to store to $value, or NULL as described above.
 * @param $value
 *   A value to store for $key.
 * @return
 *   An array mapping each $key to an array of each $value passed in
 *   for that key.
 */
function field_test_memorize($key = NULL, $value = NULL) {
  $memorize = &drupal_static(__FUNCTION__, NULL);

171
  if (!isset($key)) {
172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188
    $return = $memorize;
    $memorize = array();
    return $return;
  }
  if (is_array($memorize)) {
    $memorize[$key][] = $value;
  }
}

/**
 * Memorize calls to hook_field_create_field().
 */
function field_test_field_create_field($field) {
  $args = func_get_args();
  field_test_memorize(__FUNCTION__, $args);
}

189 190 191 192
/**
 * Implements hook_field_attach_view_alter().
 */
function field_test_field_attach_view_alter(&$output, $context) {
193
  if (!empty($context['display_options']['settings']['alter'])) {
194 195 196
    $output['test_field'][] = array('#markup' => 'field_test_field_attach_view_alter');
  }
}
197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223

/**
 * Implements hook_field_widget_properties_alter().
 */
function field_test_field_widget_properties_alter(&$widget, $context) {
  // Make the alter_test_text field 42 characters for nodes and comments.
  if (in_array($context['entity_type'], array('node', 'comment')) && ($context['field']['field_name'] == 'alter_test_text')) {
    $widget['settings']['size'] = 42;
  }
}

/**
 * Implements hook_field_widget_properties_ENTITY_TYPE_alter().
 */
function field_test_field_widget_properties_user_alter(&$widget, $context) {
  // Always use buttons for the alter_test_options field on user forms.
  if ($context['field']['field_name'] == 'alter_test_options') {
    $widget['type'] = 'options_buttons';
  }
}

/**
 * Implements hook_field_widget_form_alter().
 */
function field_test_field_widget_form_alter(&$element, &$form_state, $context) {
  switch ($context['field']['field_name']) {
    case 'alter_test_text':
224
      drupal_set_message('Field size: ' . $context['instance']->getWidget()->getSetting('size'));
225 226 227
      break;

    case 'alter_test_options':
228
      drupal_set_message('Widget type: ' . $context['instance']->getWidget()->getPluginId());
229 230
      break;
  }
231 232 233 234 235
  // Set a message if this is for the form displayed to set default value for
  // the field instance.
  if ($context['default']) {
    drupal_set_message('From hook_field_widget_form_alter(): Default form is true.');
  }
236
}
237 238 239 240

/**
 * Implements hook_query_TAG_alter() for tag 'efq_table_prefixing_test'.
 *
241
 * @see Drupal\system\Tests\Entity\EntityFieldQueryTest::testTablePrefixing()
242 243 244 245 246 247
 */
function field_test_query_efq_table_prefixing_test_alter(&$query) {
  // Add an additional join onto the entity base table. This will cause an
  // exception if the EFQ does not properly prefix the base table.
  $query->join('test_entity','te2','%alias.ftid = test_entity.ftid');
}
248

249 250 251 252 253 254 255 256 257 258 259

/**
 * Implements hook_query_TAG_alter() for tag 'efq_metadata_test'.
 *
 * @see Drupal\system\Tests\Entity\EntityQueryTest::testMetaData()
 */
function field_test_query_efq_metadata_test_alter(&$query) {
  global $efq_test_metadata;
  $efq_test_metadata = $query->getMetadata('foo');
}

260 261 262 263 264 265 266
/**
 * Implements hook_field_formatter_settings_form_alter().
 */
function field_test_field_formatter_settings_form_alter(&$element, &$form_state, $context) {
  $element['field_test_formatter_settings_form_alter'] = array(
    '#type' => 'textfield',
    '#title' => t('Formatter settings form alter'),
267
    '#default_value' => $context['formatter']->getSetting('field_test_formatter_settings_form_alter'),
268 269 270 271 272 273 274 275 276
  );
}

/**
 * Implements hook_field_formatter_settings_summary_alter().
 */
function field_test_field_formatter_settings_summary_alter(&$summary, $context) {
  $summary .= '<br />field_test_field_formatter_settings_summary_alter';
}
277 278 279 280 281 282 283 284

/**
 * Implements hook_field_extra_fields_alter().
 */
function field_test_field_extra_fields_alter(&$info) {
  // Remove all extra fields from the 'no_fields' content type;
  unset($info['node']['no_fields']);
}
285 286 287

/**
 * Implements hook_module_implements_alter().
288 289 290 291
 *
 * field_test_entity_info_alter() adds the bundles for its entities, and thus
 * needs to run before rdf_entity_info_alter().
 * @todo Remove when http://drupal.org/node/1822458 is fixed.
292 293
 */
function field_test_module_implements_alter(&$implementations, $hook) {
294
  if ($hook == 'entity_bundle_info_alter' && isset($implementations['field_test']) && isset($implementations['rdf'])) {
295 296 297 298 299 300 301
    foreach (array('field_test', 'rdf') as $module) {
      $group = $implementations[$module];
      unset($implementations[$module]);
      $implementations[$module] = $group;
    }
  }
}