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