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