annotate core/modules/field/src/Tests/Views/HandlerFieldFieldTest.php @ 6:875880e46745

Styling
author Chris Cannam
date Fri, 08 Dec 2017 13:21:27 +0000
parents 4c8ae668cc8c
children 1fec387a4317
rev   line source
Chris@0 1 <?php
Chris@0 2
Chris@0 3 namespace Drupal\field\Tests\Views;
Chris@0 4
Chris@0 5 use Drupal\Core\Field\FieldStorageDefinitionInterface;
Chris@0 6 use Drupal\views\ViewExecutable;
Chris@0 7 use Drupal\views\Views;
Chris@0 8 use Drupal\field\Entity\FieldStorageConfig;
Chris@0 9
Chris@0 10 /**
Chris@0 11 * Tests the field itself of the Field integration.
Chris@0 12 *
Chris@0 13 * @group field
Chris@0 14 * @TODO
Chris@0 15 * Check a entity-type with bundles
Chris@0 16 * Check a entity-type without bundles
Chris@0 17 * Check locale:disabled, locale:enabled and locale:enabled with another language
Chris@0 18 * Check revisions
Chris@0 19 */
Chris@0 20 class HandlerFieldFieldTest extends FieldTestBase {
Chris@0 21
Chris@0 22 /**
Chris@0 23 * {@inheritdoc}
Chris@0 24 */
Chris@0 25 public static $modules = ['node', 'field_test'];
Chris@0 26
Chris@0 27 /**
Chris@0 28 * Views used by this test.
Chris@0 29 *
Chris@0 30 * @var array
Chris@0 31 */
Chris@0 32 public static $testViews = ['test_view_fieldapi'];
Chris@0 33
Chris@0 34 /**
Chris@0 35 * Test nodes.
Chris@0 36 *
Chris@0 37 * @var \Drupal\node\NodeInterface[]
Chris@0 38 */
Chris@0 39 public $nodes;
Chris@0 40
Chris@0 41 /**
Chris@0 42 * {@inheritdoc}
Chris@0 43 */
Chris@0 44 protected function setUp() {
Chris@0 45 parent::setUp();
Chris@0 46
Chris@0 47 // Setup basic fields.
Chris@0 48 $this->setUpFieldStorages(3);
Chris@0 49
Chris@0 50 // Setup a field with cardinality > 1.
Chris@0 51 $this->fieldStorages[3] = FieldStorageConfig::create([
Chris@0 52 'field_name' => 'field_name_3',
Chris@0 53 'entity_type' => 'node',
Chris@0 54 'type' => 'string',
Chris@0 55 'cardinality' => FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED,
Chris@0 56 ]);
Chris@0 57 $this->fieldStorages[3]->save();
Chris@0 58 // Setup a field that will have no value.
Chris@0 59 $this->fieldStorages[4] = FieldStorageConfig::create([
Chris@0 60 'field_name' => 'field_name_4',
Chris@0 61 'entity_type' => 'node',
Chris@0 62 'type' => 'string',
Chris@0 63 'cardinality' => FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED,
Chris@0 64 ]);
Chris@0 65 $this->fieldStorages[4]->save();
Chris@0 66
Chris@0 67 // Setup a text field.
Chris@0 68 $this->fieldStorages[5] = FieldStorageConfig::create([
Chris@0 69 'field_name' => 'field_name_5',
Chris@0 70 'entity_type' => 'node',
Chris@0 71 'type' => 'text',
Chris@0 72 ]);
Chris@0 73 $this->fieldStorages[5]->save();
Chris@0 74
Chris@0 75 // Setup a text field with access control.
Chris@0 76 // @see field_test_entity_field_access()
Chris@0 77 $this->fieldStorages[6] = FieldStorageConfig::create([
Chris@0 78 'field_name' => 'field_no_view_access',
Chris@0 79 'entity_type' => 'node',
Chris@0 80 'type' => 'text',
Chris@0 81 ]);
Chris@0 82 $this->fieldStorages[6]->save();
Chris@0 83
Chris@0 84 $this->setUpFields();
Chris@0 85
Chris@0 86 // Create some nodes.
Chris@0 87 $this->nodes = [];
Chris@0 88 for ($i = 0; $i < 3; $i++) {
Chris@0 89 $edit = ['type' => 'page'];
Chris@0 90
Chris@0 91 foreach ([0, 1, 2, 5] as $key) {
Chris@0 92 $field_storage = $this->fieldStorages[$key];
Chris@0 93 $edit[$field_storage->getName()][0]['value'] = $this->randomMachineName(8);
Chris@0 94 }
Chris@0 95 // Add a hidden value for the no-view field.
Chris@0 96 $edit[$this->fieldStorages[6]->getName()][0]['value'] = 'ssh secret squirrel';
Chris@0 97 for ($j = 0; $j < 5; $j++) {
Chris@0 98 $edit[$this->fieldStorages[3]->getName()][$j]['value'] = $this->randomMachineName(8);
Chris@0 99 }
Chris@0 100 // Set this field to be empty.
Chris@0 101 $edit[$this->fieldStorages[4]->getName()] = [['value' => NULL]];
Chris@0 102
Chris@0 103 $this->nodes[$i] = $this->drupalCreateNode($edit);
Chris@0 104 }
Chris@0 105
Chris@0 106 $this->container->get('views.views_data')->clear();
Chris@0 107 }
Chris@0 108
Chris@0 109 /**
Chris@0 110 * Sets up the testing view with random field data.
Chris@0 111 *
Chris@0 112 * @param \Drupal\views\ViewExecutable $view
Chris@0 113 * The view to add field data to.
Chris@0 114 */
Chris@0 115 protected function prepareView(ViewExecutable $view) {
Chris@0 116 $view->storage->invalidateCaches();
Chris@0 117 $view->initDisplay();
Chris@0 118 foreach ($this->fieldStorages as $field_storage) {
Chris@0 119 $field_name = $field_storage->getName();
Chris@0 120 $view->display_handler->options['fields'][$field_name]['id'] = $field_name;
Chris@0 121 $view->display_handler->options['fields'][$field_name]['table'] = 'node__' . $field_name;
Chris@0 122 $view->display_handler->options['fields'][$field_name]['field'] = $field_name;
Chris@0 123 }
Chris@0 124 }
Chris@0 125
Chris@0 126 public function testFieldRender() {
Chris@0 127 $this->_testSimpleFieldRender();
Chris@0 128 $this->_testInaccessibleFieldRender();
Chris@0 129 $this->_testFormatterSimpleFieldRender();
Chris@0 130 $this->_testMultipleFieldRender();
Chris@0 131 }
Chris@0 132
Chris@0 133 public function _testSimpleFieldRender() {
Chris@0 134 $view = Views::getView('test_view_fieldapi');
Chris@0 135 $this->prepareView($view);
Chris@0 136 $this->executeView($view);
Chris@0 137
Chris@0 138 // Tests that the rendered fields match the actual value of the fields.
Chris@0 139 for ($i = 0; $i < 3; $i++) {
Chris@0 140 for ($key = 0; $key < 2; $key++) {
Chris@0 141 $field_name = $this->fieldStorages[$key]->getName();
Chris@0 142 $rendered_field = $view->style_plugin->getField($i, $field_name);
Chris@0 143 $expected_field = $this->nodes[$i]->$field_name->value;
Chris@0 144 $this->assertEqual($rendered_field, $expected_field);
Chris@0 145 }
Chris@0 146 }
Chris@0 147 }
Chris@0 148
Chris@0 149 public function _testInaccessibleFieldRender() {
Chris@0 150 $view = Views::getView('test_view_fieldapi');
Chris@0 151 $this->prepareView($view);
Chris@0 152 $this->executeView($view);
Chris@0 153
Chris@0 154 // Check that the field handler for the hidden field is correctly removed
Chris@0 155 // from the display.
Chris@0 156 // @see https://www.drupal.org/node/2382931
Chris@0 157 $this->assertFalse(array_key_exists('field_no_view_access', $view->field));
Chris@0 158
Chris@0 159 // Check that the access-denied field is not visible.
Chris@0 160 for ($i = 0; $i < 3; $i++) {
Chris@0 161 $field_name = $this->fieldStorages[6]->getName();
Chris@0 162 $rendered_field = $view->style_plugin->getField($i, $field_name);
Chris@0 163 $this->assertFalse($rendered_field, 'Hidden field not rendered');
Chris@0 164 }
Chris@0 165 }
Chris@0 166
Chris@0 167 /**
Chris@0 168 * Tests that fields with formatters runs as expected.
Chris@0 169 */
Chris@0 170 public function _testFormatterSimpleFieldRender() {
Chris@0 171 $view = Views::getView('test_view_fieldapi');
Chris@0 172 $this->prepareView($view);
Chris@0 173 $view->displayHandlers->get('default')->options['fields'][$this->fieldStorages[5]->getName()]['type'] = 'text_trimmed';
Chris@0 174 $view->displayHandlers->get('default')->options['fields'][$this->fieldStorages[5]->getName()]['settings'] = [
Chris@0 175 'trim_length' => 3,
Chris@0 176 ];
Chris@0 177 $this->executeView($view);
Chris@0 178
Chris@0 179 // Make sure that the formatter works as expected.
Chris@0 180 // @TODO: actually there should be a specific formatter.
Chris@0 181 for ($i = 0; $i < 2; $i++) {
Chris@0 182 $rendered_field = $view->style_plugin->getField($i, $this->fieldStorages[5]->getName());
Chris@0 183 $this->assertEqual(strlen(html_entity_decode($rendered_field)), 3);
Chris@0 184 }
Chris@0 185 }
Chris@0 186
Chris@0 187 public function _testMultipleFieldRender() {
Chris@0 188 $view = Views::getView('test_view_fieldapi');
Chris@0 189 $field_name = $this->fieldStorages[3]->getName();
Chris@0 190
Chris@0 191 // Test delta limit.
Chris@0 192 $this->prepareView($view);
Chris@0 193 $view->displayHandlers->get('default')->options['fields'][$field_name]['group_rows'] = TRUE;
Chris@0 194 $view->displayHandlers->get('default')->options['fields'][$field_name]['delta_limit'] = 3;
Chris@0 195 $this->executeView($view);
Chris@0 196
Chris@0 197 for ($i = 0; $i < 3; $i++) {
Chris@0 198 $rendered_field = $view->style_plugin->getField($i, $field_name);
Chris@0 199 $items = [];
Chris@0 200 $pure_items = $this->nodes[$i]->{$field_name}->getValue();
Chris@0 201 $pure_items = array_splice($pure_items, 0, 3);
Chris@0 202 foreach ($pure_items as $j => $item) {
Chris@0 203 $items[] = $pure_items[$j]['value'];
Chris@0 204 }
Chris@0 205 $this->assertEqual($rendered_field, implode(', ', $items), 'The amount of items is limited.');
Chris@0 206 }
Chris@0 207
Chris@0 208 // Test that an empty field is rendered without error.
Chris@0 209 $view->style_plugin->getField(4, $this->fieldStorages[4]->getName());
Chris@0 210 $view->destroy();
Chris@0 211
Chris@0 212 // Test delta limit + offset
Chris@0 213 $this->prepareView($view);
Chris@0 214 $view->displayHandlers->get('default')->options['fields'][$field_name]['group_rows'] = TRUE;
Chris@0 215 $view->displayHandlers->get('default')->options['fields'][$field_name]['delta_limit'] = 3;
Chris@0 216 $view->displayHandlers->get('default')->options['fields'][$field_name]['delta_offset'] = 1;
Chris@0 217 $this->executeView($view);
Chris@0 218
Chris@0 219 for ($i = 0; $i < 3; $i++) {
Chris@0 220 $rendered_field = $view->style_plugin->getField($i, $field_name);
Chris@0 221 $items = [];
Chris@0 222 $pure_items = $this->nodes[$i]->{$field_name}->getValue();
Chris@0 223 $pure_items = array_splice($pure_items, 1, 3);
Chris@0 224 foreach ($pure_items as $j => $item) {
Chris@0 225 $items[] = $pure_items[$j]['value'];
Chris@0 226 }
Chris@0 227 $this->assertEqual($rendered_field, implode(', ', $items), 'The amount of items is limited and the offset is correct.');
Chris@0 228 }
Chris@0 229 $view->destroy();
Chris@0 230
Chris@0 231 // Test delta limit + reverse.
Chris@0 232 $this->prepareView($view);
Chris@0 233 $view->displayHandlers->get('default')->options['fields'][$field_name]['delta_offset'] = 0;
Chris@0 234 $view->displayHandlers->get('default')->options['fields'][$field_name]['group_rows'] = TRUE;
Chris@0 235 $view->displayHandlers->get('default')->options['fields'][$field_name]['delta_limit'] = 3;
Chris@0 236 $view->displayHandlers->get('default')->options['fields'][$field_name]['delta_reversed'] = TRUE;
Chris@0 237 $this->executeView($view);
Chris@0 238
Chris@0 239 for ($i = 0; $i < 3; $i++) {
Chris@0 240 $rendered_field = $view->style_plugin->getField($i, $field_name);
Chris@0 241 $items = [];
Chris@0 242 $pure_items = $this->nodes[$i]->{$field_name}->getValue();
Chris@0 243 array_splice($pure_items, 0, -3);
Chris@0 244 $pure_items = array_reverse($pure_items);
Chris@0 245 foreach ($pure_items as $j => $item) {
Chris@0 246 $items[] = $pure_items[$j]['value'];
Chris@0 247 }
Chris@0 248 $this->assertEqual($rendered_field, implode(', ', $items), 'The amount of items is limited and they are reversed.');
Chris@0 249 }
Chris@0 250 $view->destroy();
Chris@0 251
Chris@0 252 // Test delta first last.
Chris@0 253 $this->prepareView($view);
Chris@0 254 $view->displayHandlers->get('default')->options['fields'][$field_name]['group_rows'] = TRUE;
Chris@0 255 $view->displayHandlers->get('default')->options['fields'][$field_name]['delta_limit'] = 0;
Chris@0 256 $view->displayHandlers->get('default')->options['fields'][$field_name]['delta_first_last'] = TRUE;
Chris@0 257 $view->displayHandlers->get('default')->options['fields'][$field_name]['delta_reversed'] = FALSE;
Chris@0 258 $this->executeView($view);
Chris@0 259
Chris@0 260 for ($i = 0; $i < 3; $i++) {
Chris@0 261 $rendered_field = $view->style_plugin->getField($i, $field_name);
Chris@0 262 $items = [];
Chris@0 263 $pure_items = $this->nodes[$i]->{$field_name}->getValue();
Chris@0 264 $items[] = $pure_items[0]['value'];
Chris@0 265 $items[] = $pure_items[4]['value'];
Chris@0 266 $this->assertEqual($rendered_field, implode(', ', $items), 'Items are limited to first and last.');
Chris@0 267 }
Chris@0 268 $view->destroy();
Chris@0 269
Chris@0 270 // Test delta limit + custom separator.
Chris@0 271 $this->prepareView($view);
Chris@0 272 $view->displayHandlers->get('default')->options['fields'][$field_name]['delta_first_last'] = FALSE;
Chris@0 273 $view->displayHandlers->get('default')->options['fields'][$field_name]['delta_limit'] = 3;
Chris@0 274 $view->displayHandlers->get('default')->options['fields'][$field_name]['group_rows'] = TRUE;
Chris@0 275 $view->displayHandlers->get('default')->options['fields'][$field_name]['separator'] = ':';
Chris@0 276 $this->executeView($view);
Chris@0 277
Chris@0 278 for ($i = 0; $i < 3; $i++) {
Chris@0 279 $rendered_field = $view->style_plugin->getField($i, $field_name);
Chris@0 280 $items = [];
Chris@0 281 $pure_items = $this->nodes[$i]->{$field_name}->getValue();
Chris@0 282 $pure_items = array_splice($pure_items, 0, 3);
Chris@0 283 foreach ($pure_items as $j => $item) {
Chris@0 284 $items[] = $pure_items[$j]['value'];
Chris@0 285 }
Chris@0 286 $this->assertEqual($rendered_field, implode(':', $items), 'The amount of items is limited and the custom separator is correct.');
Chris@0 287 }
Chris@0 288 $view->destroy();
Chris@0 289
Chris@0 290 // Test separator with HTML, ensure it is escaped.
Chris@0 291 $this->prepareView($view);
Chris@0 292 $view->displayHandlers->get('default')->options['fields'][$field_name]['group_rows'] = TRUE;
Chris@0 293 $view->displayHandlers->get('default')->options['fields'][$field_name]['delta_limit'] = 3;
Chris@0 294 $view->displayHandlers->get('default')->options['fields'][$field_name]['separator'] = '<h2>test</h2>';
Chris@0 295 $this->executeView($view);
Chris@0 296
Chris@0 297 for ($i = 0; $i < 3; $i++) {
Chris@0 298 $rendered_field = $view->style_plugin->getField($i, $field_name);
Chris@0 299 $items = [];
Chris@0 300 $pure_items = $this->nodes[$i]->{$field_name}->getValue();
Chris@0 301 $pure_items = array_splice($pure_items, 0, 3);
Chris@0 302 foreach ($pure_items as $j => $item) {
Chris@0 303 $items[] = $pure_items[$j]['value'];
Chris@0 304 }
Chris@0 305 $this->assertEqual($rendered_field, implode('<h2>test</h2>', $items), 'The custom separator is correctly escaped.');
Chris@0 306 }
Chris@0 307 $view->destroy();
Chris@0 308 }
Chris@0 309
Chris@0 310 }