field_test.module 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280
  1. <?php
  2. /**
  3. * @file
  4. * Helper module for the Field API tests.
  5. *
  6. * The module defines
  7. * - an entity type (field_test.entity.inc)
  8. * - a field type and its formatters and widgets (field_test.field.inc)
  9. * - a field storage backend (field_test.storage.inc)
  10. *
  11. * The main field_test.module file implements generic hooks and provides some
  12. * test helper functions
  13. */
  14. require_once DRUPAL_ROOT . '/modules/field/tests/field_test.entity.inc';
  15. require_once DRUPAL_ROOT . '/modules/field/tests/field_test.field.inc';
  16. require_once DRUPAL_ROOT . '/modules/field/tests/field_test.storage.inc';
  17. /**
  18. * Implements hook_permission().
  19. */
  20. function field_test_permission() {
  21. $perms = array(
  22. 'access field_test content' => array(
  23. 'title' => t('Access field_test content'),
  24. 'description' => t('View published field_test content.'),
  25. ),
  26. 'administer field_test content' => array(
  27. 'title' => t('Administer field_test content'),
  28. 'description' => t('Manage field_test content'),
  29. ),
  30. );
  31. return $perms;
  32. }
  33. /**
  34. * Implements hook_menu().
  35. */
  36. function field_test_menu() {
  37. $items = array();
  38. $bundles = field_info_bundles('test_entity');
  39. foreach ($bundles as $bundle_name => $bundle_info) {
  40. $bundle_url_str = str_replace('_', '-', $bundle_name);
  41. $items['test-entity/add/' . $bundle_url_str] = array(
  42. 'title' => t('Add %bundle test_entity', array('%bundle' => $bundle_info['label'])),
  43. 'page callback' => 'field_test_entity_add',
  44. 'page arguments' => array(2),
  45. 'access arguments' => array('administer field_test content'),
  46. 'type' => MENU_NORMAL_ITEM,
  47. );
  48. }
  49. $items['test-entity/manage/%field_test_entity_test/edit'] = array(
  50. 'title' => 'Edit test entity',
  51. 'page callback' => 'field_test_entity_edit',
  52. 'page arguments' => array(2),
  53. 'access arguments' => array('administer field_test content'),
  54. 'type' => MENU_NORMAL_ITEM,
  55. );
  56. $items['test-entity/nested/%field_test_entity_test/%field_test_entity_test'] = array(
  57. 'title' => 'Nested entity form',
  58. 'page callback' => 'drupal_get_form',
  59. 'page arguments' => array('field_test_entity_nested_form', 2, 3),
  60. 'access arguments' => array('administer field_test content'),
  61. 'type' => MENU_NORMAL_ITEM,
  62. );
  63. return $items;
  64. }
  65. /**
  66. * Generic op to test _field_invoke behavior.
  67. *
  68. * This simulates a field operation callback to be invoked by _field_invoke().
  69. */
  70. function field_test_field_test_op($entity_type, $entity, $field, $instance, $langcode, &$items) {
  71. return array($langcode => hash('sha256', serialize(array($entity_type, $entity, $field['field_name'], $langcode, $items))));
  72. }
  73. /**
  74. * Generic op to test _field_invoke_multiple behavior.
  75. *
  76. * This simulates a multiple field operation callback to be invoked by
  77. * _field_invoke_multiple().
  78. */
  79. function field_test_field_test_op_multiple($entity_type, $entities, $field, $instances, $langcode, &$items) {
  80. $result = array();
  81. foreach ($entities as $id => $entity) {
  82. // Entities, instances and items are assumed to be consistently grouped by
  83. // language. To verify this we try to access all the passed data structures
  84. // by entity id. If they are grouped correctly, one entity, one instance and
  85. // one array of items should be available for each entity id.
  86. $field_name = $instances[$id]['field_name'];
  87. $result[$id] = array($langcode => hash('sha256', serialize(array($entity_type, $entity, $field_name, $langcode, $items[$id]))));
  88. }
  89. return $result;
  90. }
  91. /**
  92. * Implements hook_field_available_languages_alter().
  93. */
  94. function field_test_field_available_languages_alter(&$languages, $context) {
  95. if (variable_get('field_test_field_available_languages_alter', FALSE)) {
  96. // Add an unavailable language.
  97. $languages[] = 'xx';
  98. // Remove an available language.
  99. $index = array_search('en', $languages);
  100. unset($languages[$index]);
  101. }
  102. }
  103. /**
  104. * Implements hook_field_language_alter().
  105. */
  106. function field_test_field_language_alter(&$display_language, $context) {
  107. if (variable_get('field_test_language_fallback', TRUE)) {
  108. locale_field_language_fallback($display_language, $context['entity'], $context['language']);
  109. }
  110. }
  111. /**
  112. * Store and retrieve keyed data for later verification by unit tests.
  113. *
  114. * This function is a simple in-memory key-value store with the
  115. * distinction that it stores all values for a given key instead of
  116. * just the most recently set value. field_test module hooks call
  117. * this function to record their arguments, keyed by hook name. The
  118. * unit tests later call this function to verify that the correct
  119. * hooks were called and were passed the correct arguments.
  120. *
  121. * This function ignores all calls until the first time it is called
  122. * with $key of NULL. Each time it is called with $key of NULL, it
  123. * erases all previously stored data from its internal cache, but also
  124. * returns the previously stored data to the caller. A typical usage
  125. * scenario is:
  126. *
  127. * @code
  128. * // calls to field_test_memorize() here are ignored
  129. *
  130. * // turn on memorization
  131. * field_test_memorize();
  132. *
  133. * // call some Field API functions that invoke field_test hooks
  134. * $field = field_create_field(...);
  135. *
  136. * // retrieve and reset the memorized hook call data
  137. * $mem = field_test_memorize();
  138. *
  139. * // make sure hook_field_create_field() is invoked correctly
  140. * assertEqual(count($mem['field_test_field_create_field']), 1);
  141. * assertEqual($mem['field_test_field_create_field'][0], array($field));
  142. * @endcode
  143. *
  144. * @param $key
  145. * The key under which to store to $value, or NULL as described above.
  146. * @param $value
  147. * A value to store for $key.
  148. * @return
  149. * An array mapping each $key to an array of each $value passed in
  150. * for that key.
  151. */
  152. function field_test_memorize($key = NULL, $value = NULL) {
  153. $memorize = &drupal_static(__FUNCTION__, NULL);
  154. if (!isset($key)) {
  155. $return = $memorize;
  156. $memorize = array();
  157. return $return;
  158. }
  159. if (is_array($memorize)) {
  160. $memorize[$key][] = $value;
  161. }
  162. }
  163. /**
  164. * Memorize calls to hook_field_create_field().
  165. */
  166. function field_test_field_create_field($field) {
  167. $args = func_get_args();
  168. field_test_memorize(__FUNCTION__, $args);
  169. }
  170. /**
  171. * Implements hook_entity_query_alter().
  172. */
  173. function field_test_entity_query_alter(&$query) {
  174. if (!empty($query->alterMyExecuteCallbackPlease)) {
  175. $query->executeCallback = 'field_test_dummy_field_storage_query';
  176. }
  177. }
  178. /**
  179. * Pseudo-implements hook_field_storage_query().
  180. */
  181. function field_test_dummy_field_storage_query(EntityFieldQuery $query) {
  182. // Return dummy values that will be checked by the test.
  183. return array(
  184. 'user' => array(
  185. 1 => entity_create_stub_entity('user', array(1, NULL, NULL)),
  186. ),
  187. );
  188. }
  189. /**
  190. * Implements callback_entity_info_label().
  191. *
  192. * @return
  193. * The label of the entity prefixed with "label callback".
  194. */
  195. function field_test_entity_label_callback($entity) {
  196. return 'label callback ' . $entity->ftlabel;
  197. }
  198. /**
  199. * Implements hook_field_attach_view_alter().
  200. */
  201. function field_test_field_attach_view_alter(&$output, $context) {
  202. if (!empty($context['display']['settings']['alter'])) {
  203. $output['test_field'][] = array('#markup' => 'field_test_field_attach_view_alter');
  204. }
  205. }
  206. /**
  207. * Implements hook_field_widget_properties_alter().
  208. */
  209. function field_test_field_widget_properties_alter(&$widget, $context) {
  210. // Make the alter_test_text field 42 characters for nodes and comments.
  211. if (in_array($context['entity_type'], array('node', 'comment')) && ($context['field']['field_name'] == 'alter_test_text')) {
  212. $widget['settings']['size'] = 42;
  213. }
  214. }
  215. /**
  216. * Implements hook_field_widget_properties_ENTITY_TYPE_alter().
  217. */
  218. function field_test_field_widget_properties_user_alter(&$widget, $context) {
  219. // Always use buttons for the alter_test_options field on user forms.
  220. if ($context['field']['field_name'] == 'alter_test_options') {
  221. $widget['type'] = 'options_buttons';
  222. }
  223. }
  224. /**
  225. * Implements hook_field_widget_form_alter().
  226. */
  227. function field_test_field_widget_form_alter(&$element, &$form_state, $context) {
  228. switch ($context['field']['field_name']) {
  229. case 'alter_test_text':
  230. drupal_set_message('Field size: ' . $context['instance']['widget']['settings']['size']);
  231. break;
  232. case 'alter_test_options':
  233. drupal_set_message('Widget type: ' . $context['instance']['widget']['type']);
  234. break;
  235. }
  236. }
  237. /**
  238. * Implements hook_query_TAG_alter() for tag 'efq_table_prefixing_test'.
  239. *
  240. * @see EntityFieldQueryTestCase::testTablePrefixing()
  241. */
  242. function field_test_query_efq_table_prefixing_test_alter(&$query) {
  243. // Add an additional join onto the entity base table. This will cause an
  244. // exception if the EFQ does not properly prefix the base table.
  245. $query->join('test_entity','te2','%alias.ftid = test_entity.ftid');
  246. }
  247. /**
  248. * Implements hook_query_TAG_alter() for tag 'store_global_test_query'.
  249. */
  250. function field_test_query_store_global_test_query_alter($query) {
  251. // Save the query in a global variable so that it can be examined by tests.
  252. // This can be used by any test which needs to check a query, but see
  253. // FieldSqlStorageTestCase::testFieldSqlStorageMultipleConditionsSameColumn()
  254. // for an example.
  255. $GLOBALS['test_query'] = $query;
  256. }