1<?php 2 3/** 4 * @file 5 * Helper module for the Field API tests. 6 * 7 * The module defines 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 15use Drupal\Core\Entity\EntityTypeInterface; 16use Drupal\Core\Form\FormStateInterface; 17use Drupal\Core\Render\Element; 18use Drupal\field\FieldStorageConfigInterface; 19 20require_once __DIR__ . '/field_test.entity.inc'; 21require_once __DIR__ . '/field_test.field.inc'; 22 23/** 24 * Store and retrieve keyed data for later verification by unit tests. 25 * 26 * This function is a simple in-memory key-value store with the 27 * distinction that it stores all values for a given key instead of 28 * just the most recently set value. field_test module hooks call 29 * this function to record their arguments, keyed by hook name. The 30 * unit tests later call this function to verify that the correct 31 * hooks were called and were passed the correct arguments. 32 * 33 * This function ignores all calls until the first time it is called 34 * with $key of NULL. Each time it is called with $key of NULL, it 35 * erases all previously stored data from its internal cache, but also 36 * returns the previously stored data to the caller. A typical usage 37 * scenario is: 38 * 39 * @code 40 * // calls to field_test_memorize() here are ignored 41 * 42 * // turn on memorization 43 * field_test_memorize(); 44 * 45 * // call some Field API functions that invoke field_test hooks 46 * FieldStorageConfig::create($field_definition)->save(); 47 * 48 * // retrieve and reset the memorized hook call data 49 * $mem = field_test_memorize(); 50 * 51 * // make sure hook_field_storage_config_create() is invoked correctly 52 * assertEquals(1, count($mem['field_test_field_storage_config_create'])); 53 * assertEquals(array($field), $mem['field_test_field_storage_config_create'][0]); 54 * @endcode 55 * 56 * @param $key 57 * The key under which to store to $value, or NULL as described above. 58 * @param $value 59 * A value to store for $key. 60 * 61 * @return 62 * An array mapping each $key to an array of each $value passed in 63 * for that key. 64 */ 65function field_test_memorize($key = NULL, $value = NULL) { 66 static $memorize; 67 68 if (!isset($key)) { 69 $return = $memorize; 70 $memorize = []; 71 return $return; 72 } 73 if (is_array($memorize)) { 74 $memorize[$key][] = $value; 75 } 76} 77 78/** 79 * Memorize calls to field_test_field_storage_config_create(). 80 */ 81function field_test_field_storage_config_create(FieldStorageConfigInterface $field_storage) { 82 $args = func_get_args(); 83 field_test_memorize(__FUNCTION__, $args); 84} 85 86/** 87 * Implements hook_entity_display_build_alter(). 88 */ 89function field_test_entity_display_build_alter(&$output, $context) { 90 $display_options = $context['display']->getComponent('test_field'); 91 if (isset($display_options['settings']['alter'])) { 92 $output['test_field'][] = ['#markup' => 'field_test_entity_display_build_alter']; 93 } 94 95 if (isset($output['test_field'])) { 96 $output['test_field'][] = ['#markup' => 'entity language is ' . $context['entity']->language()->getId()]; 97 } 98} 99 100/** 101 * Implements hook_field_widget_single_element_form_alter(). 102 */ 103function field_test_field_widget_single_element_form_alter(&$element, FormStateInterface $form_state, $context) { 104 // Set a message if this is for the form displayed to set default value for 105 // the field. 106 if ($context['default']) { 107 \Drupal::messenger() 108 ->addStatus('From hook_field_widget_single_element_form_alter(): Default form is true.'); 109 } 110} 111 112/** 113 * Implements hook_field_widget_complete_form_alter(). 114 */ 115function field_test_field_widget_complete_form_alter(array &$field_widget_complete_form, FormStateInterface $form_state, array $context) { 116 _field_test_alter_widget("hook_field_widget_complete_form_alter", $field_widget_complete_form, $form_state, $context); 117} 118 119/** 120 * Implements hook_field_widget_complete_WIDGET_TYPE_form_alter(). 121 */ 122function field_test_field_widget_complete_test_field_widget_multiple_form_alter(array &$field_widget_complete_form, FormStateInterface $form_state, array $context) { 123 _field_test_alter_widget("hook_field_widget_complete_WIDGET_TYPE_form_alter", $field_widget_complete_form, $form_state, $context); 124} 125 126/** 127 * Implements hook_field_widget_complete_WIDGET_TYPE_form_alter(). 128 */ 129function field_test_field_widget_complete_test_field_widget_multiple_single_value_form_alter(array &$field_widget_complete_form, FormStateInterface $form_state, array $context) { 130 _field_test_alter_widget("hook_field_widget_complete_WIDGET_TYPE_form_alter", $field_widget_complete_form, $form_state, $context); 131} 132 133/** 134 * Sets up alterations for widget alter tests. 135 * 136 * @see \Drupal\field\Tests\FormTest::widgetAlterTest() 137 */ 138function _field_test_alter_widget($hook, array &$field_widget_complete_form, FormStateInterface $form_state, array $context) { 139 $elements = &$field_widget_complete_form['widget']; 140 // Set a message if this is for the form displayed to set default value for 141 // the field. 142 if ($context['default']) { 143 \Drupal::messenger()->addStatus("From $hook(): Default form is true."); 144 } 145 $alter_info = \Drupal::state()->get("field_test.widget_alter_test"); 146 $name = $context['items']->getFieldDefinition()->getName(); 147 if (!empty($alter_info) && $hook === $alter_info['hook'] && $name === $alter_info['field_name']) { 148 $elements['#prefix'] = "From $hook(): prefix on $name parent element."; 149 foreach (Element::children($elements) as $delta => $element) { 150 $elements[$delta]['#suffix'] = "From $hook(): suffix on $name child element."; 151 } 152 } 153} 154 155/** 156 * Implements hook_query_TAG_alter() for tag 'efq_table_prefixing_test'. 157 * 158 * @see \Drupal\system\Tests\Entity\EntityFieldQueryTest::testTablePrefixing() 159 */ 160function field_test_query_efq_table_prefixing_test_alter(&$query) { 161 // Add an additional join onto the entity base table. This will cause an 162 // exception if the EFQ does not properly prefix the base table. 163 $query->join('entity_test', 'et2', '[%alias].[id] = [entity_test].[id]'); 164} 165 166/** 167 * Implements hook_query_TAG_alter() for tag 'efq_metadata_test'. 168 * 169 * @see \Drupal\system\Tests\Entity\EntityQueryTest::testMetaData() 170 */ 171function field_test_query_efq_metadata_test_alter(&$query) { 172 global $efq_test_metadata; 173 $efq_test_metadata = $query->getMetadata('foo'); 174} 175 176/** 177 * Implements hook_entity_extra_field_info_alter(). 178 */ 179function field_test_entity_extra_field_info_alter(&$info) { 180 // Remove all extra fields from the 'no_fields' content type; 181 unset($info['node']['no_fields']); 182} 183 184/** 185 * Implements hook_entity_bundle_field_info_alter(). 186 */ 187function field_test_entity_bundle_field_info_alter(&$fields, EntityTypeInterface $entity_type, $bundle) { 188 if (($field_name = \Drupal::state()->get('field_test_constraint', FALSE)) && $entity_type->id() == 'entity_test' && $bundle == 'entity_test' && !empty($fields[$field_name])) { 189 // Set a property constraint using 190 // \Drupal\Core\Field\FieldConfigInterface::setPropertyConstraints(). 191 $fields[$field_name]->setPropertyConstraints('value', [ 192 'TestField' => [ 193 'value' => -2, 194 'message' => t('%name does not accept the value @value.', ['%name' => $field_name, '@value' => -2]), 195 ], 196 ]); 197 198 // Add a property constraint using 199 // \Drupal\Core\Field\FieldConfigInterface::addPropertyConstraints(). 200 $fields[$field_name]->addPropertyConstraints('value', [ 201 'Range' => [ 202 'min' => 0, 203 'max' => 32, 204 ], 205 ]); 206 } 207} 208 209/** 210 * Implements hook_field_ui_preconfigured_options_alter(). 211 */ 212function field_test_field_ui_preconfigured_options_alter(array &$options, $field_type) { 213 if ($field_type === 'test_field_with_preconfigured_options') { 214 $options['custom_options']['entity_view_display']['settings'] = [ 215 'test_formatter_setting_multiple' => 'altered dummy test string', 216 ]; 217 } 218} 219