/** * Tests the widget. */ protected function testWidget() { $user = $this->drupalCreateUser(['administer user fields']); $this->drupalLogin($user); // Test the widget when setting a default field value. $field_name = strtolower($this->randomMachineName()); $selectable_plugin_type_id = 'block'; $field_type = 'plugin:' . $selectable_plugin_type_id; $default_selected_plugin_id = 'broken'; $this->drupalPostForm('admin/config/people/accounts/fields/add-field', ['label' => $this->randomString(), 'field_name' => $field_name, 'new_storage_type' => $field_type], t('Save and continue')); $this->drupalPostForm(NULL, [], t('Save field settings')); $this->drupalPostForm(NULL, [sprintf('default_value_input[field_%s][0][plugin_selector][container][select][container][plugin_id]', $field_name) => $default_selected_plugin_id], t('Choose')); $this->drupalPostForm(NULL, [], t('Save settings')); \Drupal::entityManager()->clearCachedFieldDefinitions(); // Get all plugin fields. $field_storage_id = 'user.field_' . $field_name; $field_storage = FieldStorageConfig::load($field_storage_id); $this->assertNotNull($field_storage); $field_id = 'user.user.field_' . $field_name; /** @var \Drupal\field\FieldConfigInterface $field */ $field = FieldConfig::load($field_id); $this->assertNotNull($field); $this->assertEqual($field->getDefaultValueLiteral()[0]['plugin_type_id'], $selectable_plugin_type_id); $this->assertEqual($field->getDefaultValueLiteral()[0]['plugin_id'], $default_selected_plugin_id); $this->assertTrue(is_array($field->getDefaultValueLiteral()[0]['plugin_configuration'])); // Test the widget when creating an entity. $entity_selected_plugin_id = 'system_breadcrumb_block'; $this->drupalPostForm('user/' . $user->id() . '/edit', [sprintf('field_%s[0][plugin_selector][container][select][container][plugin_id]', $field_name) => $entity_selected_plugin_id], t('Choose')); $this->drupalPostForm(NULL, [], t('Save')); // Test whether the widget displays field values. /** @var \Drupal\Core\Entity\ContentEntityInterface $user */ $user = entity_load_unchanged('user', $user->id()); $this->assertEqual($user->get('field_' . $field_name)->get(0)->get('plugin_type_id')->getValue(), $selectable_plugin_type_id); $this->assertEqual($user->get('field_' . $field_name)->get(0)->get('plugin_id')->getValue(), $entity_selected_plugin_id); }
/** * Tests migration of user profile fields. */ public function testUserProfileFields() { // Migrated a text field. $field_storage = FieldStorageConfig::load('user.profile_color'); $this->assertIdentical('text', $field_storage->getType(), 'Field type is text.'); $this->assertIdentical(1, $field_storage->getCardinality(), 'Text field has correct cardinality'); // Migrated a textarea. $field_storage = FieldStorageConfig::load('user.profile_biography'); $this->assertIdentical('text_long', $field_storage->getType(), 'Field type is text_long.'); // Migrated checkbox field. $field_storage = FieldStorageConfig::load('user.profile_sell_address'); $this->assertIdentical('boolean', $field_storage->getType(), 'Field type is boolean.'); // Migrated selection field. $field_storage = FieldStorageConfig::load('user.profile_sold_to'); $this->assertIdentical('list_string', $field_storage->getType(), 'Field type is list_string.'); $settings = $field_storage->getSettings(); $this->assertEqual($settings['allowed_values'], array('Pill spammers' => 'Pill spammers', 'Fitness spammers' => 'Fitness spammers', 'Back\\slash' => 'Back\\slash', 'Forward/slash' => 'Forward/slash', 'Dot.in.the.middle' => 'Dot.in.the.middle', 'Faithful servant' => 'Faithful servant', 'Anonymous donor' => 'Anonymous donor')); $this->assertIdentical('list_string', $field_storage->getType(), 'Field type is list_string.'); // Migrated list field. $field_storage = FieldStorageConfig::load('user.profile_bands'); $this->assertIdentical('text', $field_storage->getType(), 'Field type is text.'); $this->assertIdentical(-1, $field_storage->getCardinality(), 'List field has correct cardinality'); /* // Migrated URL field. $field_storage = FieldStorageConfig::load('user.profile_blog'); $this->assertIdentical('link', $field_storage->getType(), 'Field type is link.'); */ // Migrated date field. $field_storage = FieldStorageConfig::load('user.profile_birthdate'); $this->assertIdentical('datetime', $field_storage->getType(), 'Field type is datetime.'); $this->assertIdentical('date', $field_storage->getSettings()['datetime_type']); }
/** * Test the user picture field migration. */ public function testUserPictureField() { /** @var \Drupal\field\FieldStorageConfigInterface $field_storage */ $field_storage = FieldStorageConfig::load('user.user_picture'); $this->assertTrue($field_storage instanceof FieldStorageConfigInterface); $this->assertIdentical('user.user_picture', $field_storage->id()); $this->assertIdentical('image', $field_storage->getType()); $this->assertIdentical('user', $field_storage->getTargetEntityTypeId()); }
/** * Tests the Drupal 6 field to Drupal 8 migration. */ public function testFields() { // Text field. /** @var \Drupal\field\Entity\FieldStorageConfig $field_storage */ $field_storage = FieldStorageConfig::load('node.field_test'); $expected = array('max_length' => 255); $this->assertIdentical("text", $field_storage->getType(), t('Field type is @fieldtype. It should be text.', array('@fieldtype' => $field_storage->getType()))); $this->assertIdentical($expected, $field_storage->getSettings(), "Field type text settings are correct"); // Integer field. $field_storage = FieldStorageConfig::load('node.field_test_two'); $this->assertIdentical("integer", $field_storage->getType(), t('Field type is @fieldtype. It should be integer.', array('@fieldtype' => $field_storage->getType()))); // Float field. $field_storage = FieldStorageConfig::load('node.field_test_three'); $this->assertIdentical("decimal", $field_storage->getType(), t('Field type is @fieldtype. It should be decimal.', array('@fieldtype' => $field_storage->getType()))); // Link field. $field_storage = FieldStorageConfig::load('node.field_test_link'); $this->assertIdentical("link", $field_storage->getType(), t('Field type is @fieldtype. It should be link.', array('@fieldtype' => $field_storage->getType()))); // File field. $field_storage = FieldStorageConfig::load('node.field_test_filefield'); $this->assertIdentical("file", $field_storage->getType(), t('Field type is @fieldtype. It should be file.', array('@fieldtype' => $field_storage->getType()))); $field_storage = FieldStorageConfig::load('node.field_test_imagefield'); $this->assertIdentical("image", $field_storage->getType(), t('Field type is @fieldtype. It should be image.', array('@fieldtype' => $field_storage->getType()))); $settings = $field_storage->getSettings(); $this->assertIdentical('file', $settings['target_type']); $this->assertIdentical('public', $settings['uri_scheme']); $this->assertIdentical(array(), array_filter($settings['default_image'])); // Phone field. $field_storage = FieldStorageConfig::load('node.field_test_phone'); $this->assertIdentical("telephone", $field_storage->getType(), t('Field type is @fieldtype. It should be telephone.', array('@fieldtype' => $field_storage->getType()))); // Date field. $field_storage = FieldStorageConfig::load('node.field_test_datetime'); $this->assertIdentical("datetime", $field_storage->getType(), t('Field type is @fieldtype. It should be datetime.', array('@fieldtype' => $field_storage->getType()))); // Decimal field with radio buttons. $field_storage = FieldStorageConfig::load('node.field_test_decimal_radio_buttons'); $this->assertIdentical("list_float", $field_storage->getType(), t('Field type is @fieldtype. It should be list_float.', array('@fieldtype' => $field_storage->getType()))); $this->assertNotNull($field_storage->getSetting('allowed_values')['1.2'], t('First allowed value key is set to 1.2')); $this->assertNotNull($field_storage->getSetting('allowed_values')['2.1'], t('Second allowed value key is set to 2.1')); $this->assertIdentical('1.2', $field_storage->getSetting('allowed_values')['1.2'], t('First allowed value is set to 1.2')); $this->assertIdentical('2.1', $field_storage->getSetting('allowed_values')['2.1'], t('Second allowed value is set to 1.2')); // Float field with a single checkbox. $field_storage = FieldStorageConfig::load('node.field_test_float_single_checkbox'); $this->assertIdentical("boolean", $field_storage->getType(), t('Field type is @fieldtype. It should be boolean.', array('@fieldtype' => $field_storage->getType()))); // Integer field with a select list. $field_storage = FieldStorageConfig::load('node.field_test_integer_selectlist'); $this->assertIdentical("list_integer", $field_storage->getType(), t('Field type is @fieldtype. It should be list_integer.', array('@fieldtype' => $field_storage->getType()))); $this->assertNotNull($field_storage->getSetting('allowed_values')['1234'], t('First allowed value key is set to 1234')); $this->assertNotNull($field_storage->getSetting('allowed_values')['2341'], t('Second allowed value key is set to 2341')); $this->assertNotNull($field_storage->getSetting('allowed_values')['3412'], t('Third allowed value key is set to 3412')); $this->assertNotNull($field_storage->getSetting('allowed_values')['4123'], t('Fourth allowed value key is set to 4123')); $this->assertIdentical('1234', $field_storage->getSetting('allowed_values')['1234'], t('First allowed value is set to 1234')); $this->assertIdentical('2341', $field_storage->getSetting('allowed_values')['2341'], t('Second allowed value is set to 2341')); $this->assertIdentical('3412', $field_storage->getSetting('allowed_values')['3412'], t('Third allowed value is set to 3412')); $this->assertIdentical('4123', $field_storage->getSetting('allowed_values')['4123'], t('Fourth allowed value is set to 4123')); // Text field with a single checkbox. $field_storage = FieldStorageConfig::load('node.field_test_text_single_checkbox'); $this->assertIdentical("boolean", $field_storage->getType(), t('Field type is @fieldtype. It should be boolean.', array('@fieldtype' => $field_storage->getType()))); }
/** * Asserts a comment field entity. * * @param string $id * The entity ID. * @param string $comment_type * The comment type (bundle ID) the field references. */ protected function assertEntity($id, $comment_type) { $entity = FieldStorageConfig::load($id); $this->assertTrue($entity instanceof FieldStorageConfigInterface); /** @var \Drupal\field\FieldStorageConfigInterface $entity */ $this->assertIdentical('node', $entity->getTargetEntityTypeId()); $this->assertIdentical('comment', $entity->getType()); $this->assertIdentical($comment_type, $entity->getSetting('comment_type')); }
/** * Tests the Drupal 6 vocabulary-node type association to Drupal 8 migration. */ public function testVocabularyField() { // Test that the field exists. $field_storage_id = 'node.tags'; $field_storage = FieldStorageConfig::load($field_storage_id); $this->assertIdentical($field_storage_id, $field_storage->id()); $settings = $field_storage->getSettings(); $this->assertIdentical('taxonomy_term', $settings['target_type'], "Target type is correct."); $this->assertIdentical(array('node', 'tags'), Migration::load('d6_vocabulary_field')->getIdMap()->lookupDestinationID(array(4)), "Test IdMap"); }
/** * Tests the Drupal 6 vocabulary-node type association to Drupal 8 migration. */ public function testVocabularyField() { // Test that the field exists. $field_storage_id = 'node.tags'; $field_storage = FieldStorageConfig::load($field_storage_id); $this->assertIdentical($field_storage_id, $field_storage->id()); $settings = $field_storage->getSettings(); $this->assertIdentical($settings['allowed_values'][0]['vocabulary'], 'tags', "Vocabulary has correct settings."); $this->assertIdentical(array('node', 'tags'), entity_load('migration', 'd6_vocabulary_field')->getIdMap()->lookupDestinationID(array(4)), "Test IdMap"); }
/** * Tests the Drupal 6 vocabulary-node type association to Drupal 8 migration. */ public function testVocabularyField() { // Test that the field exists. $field_storage_id = 'node.tags'; /** @var \Drupal\field\FieldStorageConfigInterface $field_storage */ $field_storage = FieldStorageConfig::load($field_storage_id); $this->assertIdentical($field_storage_id, $field_storage->id()); $settings = $field_storage->getSettings(); $this->assertIdentical('taxonomy_term', $settings['target_type'], "Target type is correct."); $this->assertIdentical(1, $field_storage->getCardinality(), "Field cardinality in 1."); $this->assertIdentical(array('node', 'tags'), $this->getMigration('d6_vocabulary_field')->getIdMap()->lookupDestinationID(array(4)), "Test IdMap"); }
/** * {@inheritdoc} * * Create nodes with relative dates of yesterday, today, and tomorrow. */ public function setUp() { parent::setUp(); // Set to 'today'. static::$date = REQUEST_TIME; // Change field storage to date-only. $storage = FieldStorageConfig::load('node.' . static::$field_name); $storage->setSetting('datetime_type', DateTimeItem::DATETIME_TYPE_DATE); $storage->save(); $dates = [\Drupal::service('date.formatter')->format(static::$date + 86400, 'custom', DATETIME_DATE_STORAGE_FORMAT, DATETIME_STORAGE_TIMEZONE), \Drupal::service('date.formatter')->format(static::$date, 'custom', DATETIME_DATE_STORAGE_FORMAT, DATETIME_STORAGE_TIMEZONE), \Drupal::service('date.formatter')->format(static::$date - 86400, 'custom', DATETIME_DATE_STORAGE_FORMAT, DATETIME_STORAGE_TIMEZONE)]; foreach ($dates as $date) { $this->nodes[] = $this->drupalCreateNode(['field_date' => ['value' => $date]]); } }
protected function setUp() { parent::setUp(); $this->fieldName = Unicode::strtolower($this->randomMachineName() . '_field_name'); $field_storage = array('field_name' => $this->fieldName, 'entity_type' => $this->entityTypeId, 'type' => 'test_field', 'cardinality' => 4); entity_create('field_storage_config', $field_storage)->save(); $this->fieldStorage = FieldStorageConfig::load($this->entityTypeId . '.' . $this->fieldName); $field = array('field_storage' => $this->fieldStorage, 'bundle' => $this->entityTypeId); entity_create('field_config', $field)->save(); $this->field = FieldConfig::load($this->entityTypeId . '.' . $field['bundle'] . '.' . $this->fieldName); entity_get_form_display($this->entityTypeId, $this->entityTypeId, 'default')->setComponent($this->fieldName)->save(); for ($i = 0; $i < 3; ++$i) { ConfigurableLanguage::create(array('id' => 'l' . $i, 'label' => $this->randomString()))->save(); } }
/** * Tests that comments are deleted with the node. */ function testNodeDeletion() { $this->drupalLogin($this->webUser); $comment = $this->postComment($this->node, $this->randomMachineName(), $this->randomMachineName()); $this->assertTrue($comment->id(), 'The comment could be loaded.'); $this->node->delete(); $this->assertFalse(Comment::load($comment->id()), 'The comment could not be loaded after the node was deleted.'); // Make sure the comment field storage and all its fields are deleted when // the node type is deleted. $this->assertNotNull(FieldStorageConfig::load('node.comment'), 'Comment field storage exists'); $this->assertNotNull(FieldConfig::load('node.article.comment'), 'Comment field exists'); // Delete the node type. entity_delete_multiple('node_type', array($this->node->bundle())); $this->assertNull(FieldStorageConfig::load('node.comment'), 'Comment field storage deleted'); $this->assertNull(FieldConfig::load('node.article.comment'), 'Comment field deleted'); }
/** * Tests migrating D7 fields to field_storage_config entities, then rolling back. */ public function testFields() { // Test that the fields have migrated (prior to rollback). parent::testFields(); $this->executeRollback('d7_field'); // Check that fields have been rolled back. $rolled_back_field_ids = ['comment.field_integer', 'node.taxonomy_forums', 'node.field_integer', 'node.field_tags', 'node.field_term_reference', 'node.field_text_list', 'node.field_text', 'node.field_phone', 'node.field_file', 'node.field_images', 'node.field_image', 'node.field_long_text', 'node.field_date_with_end_time', 'node.field_integer_list', 'node.field_date', 'node.field_link', 'node.field_float', 'node.field_boolean', 'node.field_email', 'user.field_file']; foreach ($rolled_back_field_ids as $field_id) { $this->assertNull(FieldStorageConfig::load($field_id)); } // Check that fields that should persist have not been rolled back. $non_rolled_back_field_ids = ['node.body', 'comment.comment_body']; foreach ($non_rolled_back_field_ids as $field_id) { $this->assertNotNull(FieldStorageConfig::load($field_id)); } }
/** * Tests the block content body field migration. */ public function testBlockContentBodyFieldMigration() { /** @var \Drupal\field\FieldStorageConfigInterface $storage */ $storage = FieldStorageConfig::load('block_content.body'); $this->assertTrue($storage instanceof FieldStorageConfigInterface); $this->assertIdentical('block_content', $storage->getTargetEntityTypeId()); $this->assertIdentical(['basic'], array_values($storage->getBundles())); $this->assertIdentical('body', $storage->getName()); /** @var \Drupal\field\FieldConfigInterface $field */ $field = FieldConfig::load('block_content.basic.body'); $this->assertTrue($field instanceof FieldConfigInterface); $this->assertIdentical('block_content', $field->getTargetEntityTypeId()); $this->assertIdentical('basic', $field->getTargetBundle()); $this->assertIdentical('body', $field->getName()); $this->assertIdentical('Body', $field->getLabel()); }
/** * Asserts various aspects of a field_storage_config entity. * * @param string $id * The entity ID in the form ENTITY_TYPE.FIELD_NAME. * @param string $expected_type * The expected field type. * @param boolean $expected_translatable * Whether or not the field is expected to be translatable. * @param integer $expected_cardinality * The expected cardinality of the field. */ protected function assertEntity($id, $expected_type, $expected_translatable, $expected_cardinality) { list($expected_entity_type, $expected_name) = explode('.', $id); /** @var \Drupal\field\FieldStorageConfigInterface $field */ $field = FieldStorageConfig::load($id); $this->assertTrue($field instanceof FieldStorageConfigInterface); $this->assertIdentical($expected_name, $field->getName()); $this->assertIdentical($expected_type, $field->getType()); // FieldStorageConfig::$translatable is TRUE by default, so it is useful // to test for FALSE here. $this->assertEqual($expected_translatable, $field->isTranslatable()); $this->assertIdentical($expected_entity_type, $field->getTargetEntityTypeId()); if ($expected_cardinality === 1) { $this->assertFalse($field->isMultiple()); } else { $this->assertTrue($field->isMultiple()); } $this->assertIdentical($expected_cardinality, $field->getCardinality()); }
/** * Tests anonymous comment functionality. */ function testCommentFunctionality() { $limited_user = $this->drupalCreateUser(array('administer entity_test fields')); $this->drupalLogin($limited_user); // Test that default field exists. $this->drupalGet('entity_test/structure/entity_test/fields'); $this->assertText(t('Comments')); $this->assertLinkByHref('entity_test/structure/entity_test/fields/entity_test.entity_test.comment'); // Test widget hidden option is not visible when there's no comments. $this->drupalGet('entity_test/structure/entity_test/fields/entity_test.entity_test.comment'); $this->assertResponse(200); $this->assertNoField('edit-default-value-input-comment-und-0-status-0'); // Test that field to change cardinality is not available. $this->drupalGet('entity_test/structure/entity_test/fields/entity_test.entity_test.comment/storage'); $this->assertResponse(200); $this->assertNoField('cardinality_number'); $this->assertNoField('cardinality'); $this->drupalLogin($this->adminUser); // Test breadcrumb on comment add page. $this->drupalGet('comment/reply/entity_test/' . $this->entity->id() . '/comment'); $xpath = '//nav[@class="breadcrumb"]/ol/li[last()]/a'; $this->assertEqual(current($this->xpath($xpath)), $this->entity->label(), 'Last breadcrumb item is equal to node title on comment reply page.'); // Post a comment. /** @var \Drupal\comment\CommentInterface $comment1 */ $comment1 = $this->postComment($this->entity, $this->randomMachineName(), $this->randomMachineName()); $this->assertTrue($this->commentExists($comment1), 'Comment on test entity exists.'); // Test breadcrumb on comment reply page. $this->drupalGet('comment/reply/entity_test/' . $this->entity->id() . '/comment/' . $comment1->id()); $xpath = '//nav[@class="breadcrumb"]/ol/li[last()]/a'; $this->assertEqual(current($this->xpath($xpath)), $comment1->getSubject(), 'Last breadcrumb item is equal to comment title on comment reply page.'); // Test breadcrumb on comment edit page. $this->drupalGet('comment/' . $comment1->id() . '/edit'); $xpath = '//nav[@class="breadcrumb"]/ol/li[last()]/a'; $this->assertEqual(current($this->xpath($xpath)), $comment1->getSubject(), 'Last breadcrumb item is equal to comment subject on edit page.'); // Test breadcrumb on comment delete page. $this->drupalGet('comment/' . $comment1->id() . '/delete'); $xpath = '//nav[@class="breadcrumb"]/ol/li[last()]/a'; $this->assertEqual(current($this->xpath($xpath)), $comment1->getSubject(), 'Last breadcrumb item is equal to comment subject on delete confirm page.'); // Unpublish the comment. $this->performCommentOperation($comment1, 'unpublish'); $this->drupalGet('admin/content/comment/approval'); $this->assertRaw('comments[' . $comment1->id() . ']', 'Comment was unpublished.'); // Publish the comment. $this->performCommentOperation($comment1, 'publish', TRUE); $this->drupalGet('admin/content/comment'); $this->assertRaw('comments[' . $comment1->id() . ']', 'Comment was published.'); // Delete the comment. $this->performCommentOperation($comment1, 'delete'); $this->drupalGet('admin/content/comment'); $this->assertNoRaw('comments[' . $comment1->id() . ']', 'Comment was deleted.'); // Post another comment. $comment1 = $this->postComment($this->entity, $this->randomMachineName(), $this->randomMachineName()); $this->assertTrue($this->commentExists($comment1), 'Comment on test entity exists.'); // Check that the comment was found. $this->drupalGet('admin/content/comment'); $this->assertRaw('comments[' . $comment1->id() . ']', 'Comment was published.'); // Check that entity access applies to administrative page. $this->assertText($this->entity->label(), 'Name of commented account found.'); $limited_user = $this->drupalCreateUser(array('administer comments')); $this->drupalLogin($limited_user); $this->drupalGet('admin/content/comment'); $this->assertNoText($this->entity->label(), 'No commented account name found.'); $this->drupalLogout(); // Deny anonymous users access to comments. user_role_change_permissions(RoleInterface::ANONYMOUS_ID, array('access comments' => FALSE, 'post comments' => FALSE, 'skip comment approval' => FALSE, 'view test entity' => TRUE)); // Attempt to view comments while disallowed. $this->drupalGet('entity-test/' . $this->entity->id()); $this->assertNoPattern('@<h2[^>]*>Comments</h2>@', 'Comments were not displayed.'); $this->assertNoLink('Add new comment', 'Link to add comment was found.'); // Attempt to view test entity comment form while disallowed. $this->drupalGet('comment/reply/entity_test/' . $this->entity->id() . '/comment'); $this->assertResponse(403); $this->assertNoFieldByName('subject[0][value]', '', 'Subject field not found.'); $this->assertNoFieldByName('comment_body[0][value]', '', 'Comment field not found.'); user_role_change_permissions(RoleInterface::ANONYMOUS_ID, array('access comments' => TRUE, 'post comments' => FALSE, 'view test entity' => TRUE, 'skip comment approval' => FALSE)); $this->drupalGet('entity_test/' . $this->entity->id()); $this->assertPattern('@<h2[^>]*>Comments</h2>@', 'Comments were displayed.'); $this->assertLink('Log in', 0, 'Link to log in was found.'); $this->assertLink('register', 0, 'Link to register was found.'); $this->assertNoFieldByName('subject[0][value]', '', 'Subject field not found.'); $this->assertNoFieldByName('comment_body[0][value]', '', 'Comment field not found.'); // Test the combination of anonymous users being able to post, but not view // comments, to ensure that access to post comments doesn't grant access to // view them. user_role_change_permissions(RoleInterface::ANONYMOUS_ID, array('access comments' => FALSE, 'post comments' => TRUE, 'skip comment approval' => TRUE, 'view test entity' => TRUE)); $this->drupalGet('entity_test/' . $this->entity->id()); $this->assertNoPattern('@<h2[^>]*>Comments</h2>@', 'Comments were not displayed.'); $this->assertFieldByName('subject[0][value]', '', 'Subject field found.'); $this->assertFieldByName('comment_body[0][value]', '', 'Comment field found.'); $this->drupalGet('comment/reply/entity_test/' . $this->entity->id() . '/comment/' . $comment1->id()); $this->assertResponse(403); $this->assertNoText($comment1->getSubject(), 'Comment not displayed.'); // Test comment field widget changes. $limited_user = $this->drupalCreateUser(array('administer entity_test fields', 'view test entity', 'administer entity_test content')); $this->drupalLogin($limited_user); $this->drupalGet('entity_test/structure/entity_test/fields/entity_test.entity_test.comment'); $this->assertNoFieldChecked('edit-default-value-input-comment-0-status-0'); $this->assertNoFieldChecked('edit-default-value-input-comment-0-status-1'); $this->assertFieldChecked('edit-default-value-input-comment-0-status-2'); // Test comment option change in field settings. $edit = array('default_value_input[comment][0][status]' => CommentItemInterface::CLOSED, 'settings[anonymous]' => COMMENT_ANONYMOUS_MAY_CONTACT); $this->drupalPostForm(NULL, $edit, t('Save settings')); $this->drupalGet('entity_test/structure/entity_test/fields/entity_test.entity_test.comment'); $this->assertNoFieldChecked('edit-default-value-input-comment-0-status-0'); $this->assertFieldChecked('edit-default-value-input-comment-0-status-1'); $this->assertNoFieldChecked('edit-default-value-input-comment-0-status-2'); $this->assertFieldByName('settings[anonymous]', COMMENT_ANONYMOUS_MAY_CONTACT); // Add a new comment-type. $bundle = CommentType::create(array('id' => 'foobar', 'label' => 'Foobar', 'description' => '', 'target_entity_type_id' => 'entity_test')); $bundle->save(); // Add a new comment field. $storage_edit = array('settings[comment_type]' => 'foobar'); $this->fieldUIAddNewField('entity_test/structure/entity_test', 'foobar', 'Foobar', 'comment', $storage_edit); // Add a third comment field. $this->fieldUIAddNewField('entity_test/structure/entity_test', 'barfoo', 'BarFoo', 'comment', $storage_edit); // Check the field contains the correct comment type. $field_storage = FieldStorageConfig::load('entity_test.field_barfoo'); $this->assertTrue($field_storage); $this->assertEqual($field_storage->getSetting('comment_type'), 'foobar'); $this->assertEqual($field_storage->getCardinality(), 1); // Test the new entity commenting inherits default. $random_label = $this->randomMachineName(); $data = array('bundle' => 'entity_test', 'name' => $random_label); $new_entity = entity_create('entity_test', $data); $new_entity->save(); $this->drupalGet('entity_test/manage/' . $new_entity->id()); $this->assertNoFieldChecked('edit-field-foobar-0-status-1'); $this->assertFieldChecked('edit-field-foobar-0-status-2'); $this->assertNoField('edit-field-foobar-0-status-0'); // @todo Check proper url and form https://www.drupal.org/node/2458323 $this->drupalGet('comment/reply/entity_test/comment/' . $new_entity->id()); $this->assertNoFieldByName('subject[0][value]', '', 'Subject field found.'); $this->assertNoFieldByName('comment_body[0][value]', '', 'Comment field found.'); // Test removal of comment_body field. $limited_user = $this->drupalCreateUser(array('administer entity_test fields', 'post comments', 'administer comment fields', 'administer comment types')); $this->drupalLogin($limited_user); $this->drupalGet('comment/reply/entity_test/' . $this->entity->id() . '/comment'); $this->assertFieldByName('comment_body[0][value]', '', 'Comment body field found.'); $this->fieldUIDeleteField('admin/structure/comment/manage/comment', 'comment.comment.comment_body', 'Comment', 'Comment settings'); $this->drupalGet('comment/reply/entity_test/' . $this->entity->id() . '/comment'); $this->assertNoFieldByName('comment_body[0][value]', '', 'Comment body field not found.'); // Set subject field to autogenerate it. $edit = ['subject[0][value]' => '']; $this->drupalPostForm(NULL, $edit, t('Save')); }
/** * Tests cache tags presence and invalidation of the entity when referenced. * * Tests the following cache tags: * - entity type view cache tag: "<entity type>_view" * - entity cache tag: "<entity type>:<entity ID>" * - entity type list cache tag: "<entity type>_list" * - referencing entity type view cache tag: "<referencing entity type>_view" * - referencing entity type cache tag: "<referencing entity type>:<referencing entity ID>" */ public function testReferencedEntity() { $entity_type = $this->entity->getEntityTypeId(); $referencing_entity_url = $this->referencing_entity->urlInfo('canonical'); $non_referencing_entity_url = $this->non_referencing_entity->urlInfo('canonical'); $listing_url = Url::fromRoute('entity.entity_test.collection_referencing_entities', ['entity_reference_field_name' => $entity_type . '_reference', 'referenced_entity_type' => $entity_type, 'referenced_entity_id' => $this->entity->id()]); $empty_entity_listing_url = Url::fromRoute('entity.entity_test.collection_empty', ['entity_type_id' => $entity_type]); $nonempty_entity_listing_url = Url::fromRoute('entity.entity_test.collection_labels_alphabetically', ['entity_type_id' => $entity_type]); // The default cache contexts for rendered entities. $entity_cache_contexts = ['theme', 'user.roles']; // Cache tags present on every rendered page. $page_cache_tags = Cache::mergeTags(['rendered'], \Drupal::moduleHandler()->moduleExists('block') ? ['config:block_list'] : []); $view_cache_tag = array(); if ($this->entity->getEntityType()->hasHandlerClass('view_builder')) { $view_cache_tag = \Drupal::entityManager()->getViewBuilder($entity_type)->getCacheTags(); } // Generate the cache tags for the (non) referencing entities. $referencing_entity_cache_tags = Cache::mergeTags($this->referencing_entity->getCacheTags(), \Drupal::entityManager()->getViewBuilder('entity_test')->getCacheTags(), $this->entity->getCacheTags(), $this->getAdditionalCacheTagsForEntity($this->entity), $view_cache_tag, ['rendered']); $non_referencing_entity_cache_tags = Cache::mergeTags($this->non_referencing_entity->getCacheTags(), \Drupal::entityManager()->getViewBuilder('entity_test')->getCacheTags(), ['rendered']); // Generate the cache tags for all two possible entity listing paths. // 1. list cache tag only (listing query has no match) // 2. list cache tag plus entity cache tag (listing query has a match) $empty_entity_listing_cache_tags = Cache::mergeTags($this->entity->getEntityType()->getListCacheTags(), $page_cache_tags); $nonempty_entity_listing_cache_tags = Cache::mergeTags($this->entity->getEntityType()->getListCacheTags(), $this->entity->getCacheTags(), $this->getAdditionalCacheTagsForEntityListing($this->entity), $page_cache_tags); $this->pass("Test referencing entity.", 'Debug'); $this->verifyPageCache($referencing_entity_url, 'MISS'); // Verify a cache hit, but also the presence of the correct cache tags. $this->verifyPageCache($referencing_entity_url, 'HIT', Cache::mergeTags($referencing_entity_cache_tags, $page_cache_tags)); // Also verify the existence of an entity render cache entry. $cache_keys = ['entity_view', 'entity_test', $this->referencing_entity->id(), 'full']; $cid = $this->createCacheId($cache_keys, $entity_cache_contexts); $redirected_cid = $this->createRedirectedCacheId($cache_keys, $entity_cache_contexts); $this->verifyRenderCache($cid, $referencing_entity_cache_tags, $redirected_cid); $this->pass("Test non-referencing entity.", 'Debug'); $this->verifyPageCache($non_referencing_entity_url, 'MISS'); // Verify a cache hit, but also the presence of the correct cache tags. $this->verifyPageCache($non_referencing_entity_url, 'HIT', Cache::mergeTags($non_referencing_entity_cache_tags, $page_cache_tags)); // Also verify the existence of an entity render cache entry. $cache_keys = ['entity_view', 'entity_test', $this->non_referencing_entity->id(), 'full']; $cid = $this->createCacheId($cache_keys, $entity_cache_contexts); $this->verifyRenderCache($cid, $non_referencing_entity_cache_tags); $this->pass("Test listing of referencing entities.", 'Debug'); // Prime the page cache for the listing of referencing entities. $this->verifyPageCache($listing_url, 'MISS'); // Verify a cache hit, but also the presence of the correct cache tags. $this->verifyPageCache($listing_url, 'HIT', Cache::mergeTags($referencing_entity_cache_tags, $page_cache_tags)); $this->pass("Test empty listing.", 'Debug'); // Prime the page cache for the empty listing. $this->verifyPageCache($empty_entity_listing_url, 'MISS'); // Verify a cache hit, but also the presence of the correct cache tags. $this->verifyPageCache($empty_entity_listing_url, 'HIT', $empty_entity_listing_cache_tags); // Verify the entity type's list cache contexts are present. $contexts_in_header = $this->drupalGetHeader('X-Drupal-Cache-Contexts'); $this->assertEqual($this->getAdditionalCacheContextsForEntityListing(), empty($contexts_in_header) ? [] : explode(' ', $contexts_in_header)); $this->pass("Test listing containing referenced entity.", 'Debug'); // Prime the page cache for the listing containing the referenced entity. $this->verifyPageCache($nonempty_entity_listing_url, 'MISS', $nonempty_entity_listing_cache_tags); // Verify a cache hit, but also the presence of the correct cache tags. $this->verifyPageCache($nonempty_entity_listing_url, 'HIT', $nonempty_entity_listing_cache_tags); // Verify the entity type's list cache contexts are present. $contexts_in_header = $this->drupalGetHeader('X-Drupal-Cache-Contexts'); $this->assertEqual($this->getAdditionalCacheContextsForEntityListing(), empty($contexts_in_header) ? [] : explode(' ', $contexts_in_header)); // Verify that after modifying the referenced entity, there is a cache miss // for every route except the one for the non-referencing entity. $this->pass("Test modification of referenced entity.", 'Debug'); $this->entity->save(); $this->verifyPageCache($referencing_entity_url, 'MISS'); $this->verifyPageCache($listing_url, 'MISS'); $this->verifyPageCache($empty_entity_listing_url, 'MISS'); $this->verifyPageCache($nonempty_entity_listing_url, 'MISS'); $this->verifyPageCache($non_referencing_entity_url, 'HIT'); // Verify cache hits. $this->verifyPageCache($referencing_entity_url, 'HIT'); $this->verifyPageCache($listing_url, 'HIT'); $this->verifyPageCache($empty_entity_listing_url, 'HIT'); $this->verifyPageCache($nonempty_entity_listing_url, 'HIT'); // Verify that after modifying the referencing entity, there is a cache miss // for every route except the ones for the non-referencing entity and the // empty entity listing. $this->pass("Test modification of referencing entity.", 'Debug'); $this->referencing_entity->save(); $this->verifyPageCache($referencing_entity_url, 'MISS'); $this->verifyPageCache($listing_url, 'MISS'); $this->verifyPageCache($nonempty_entity_listing_url, 'HIT'); $this->verifyPageCache($non_referencing_entity_url, 'HIT'); $this->verifyPageCache($empty_entity_listing_url, 'HIT'); // Verify cache hits. $this->verifyPageCache($referencing_entity_url, 'HIT'); $this->verifyPageCache($listing_url, 'HIT'); $this->verifyPageCache($nonempty_entity_listing_url, 'HIT'); // Verify that after modifying the non-referencing entity, there is a cache // miss only for the non-referencing entity route. $this->pass("Test modification of non-referencing entity.", 'Debug'); $this->non_referencing_entity->save(); $this->verifyPageCache($referencing_entity_url, 'HIT'); $this->verifyPageCache($listing_url, 'HIT'); $this->verifyPageCache($empty_entity_listing_url, 'HIT'); $this->verifyPageCache($nonempty_entity_listing_url, 'HIT'); $this->verifyPageCache($non_referencing_entity_url, 'MISS'); // Verify cache hits. $this->verifyPageCache($non_referencing_entity_url, 'HIT'); if ($this->entity->getEntityType()->hasHandlerClass('view_builder')) { // Verify that after modifying the entity's display, there is a cache miss // for both the referencing entity, and the listing of referencing // entities, but not for any other routes. $referenced_entity_view_mode = $this->selectViewMode($this->entity->getEntityTypeId()); $this->pass("Test modification of referenced entity's '{$referenced_entity_view_mode}' display.", 'Debug'); $entity_display = entity_get_display($entity_type, $this->entity->bundle(), $referenced_entity_view_mode); $entity_display->save(); $this->verifyPageCache($referencing_entity_url, 'MISS'); $this->verifyPageCache($listing_url, 'MISS'); $this->verifyPageCache($non_referencing_entity_url, 'HIT'); $this->verifyPageCache($empty_entity_listing_url, 'HIT'); $this->verifyPageCache($nonempty_entity_listing_url, 'HIT'); // Verify cache hits. $this->verifyPageCache($referencing_entity_url, 'HIT'); $this->verifyPageCache($listing_url, 'HIT'); } $bundle_entity_type = $this->entity->getEntityType()->getBundleEntityType(); if ($bundle_entity_type !== 'bundle') { // Verify that after modifying the corresponding bundle entity, there is a // cache miss for both the referencing entity, and the listing of // referencing entities, but not for any other routes. $this->pass("Test modification of referenced entity's bundle entity.", 'Debug'); $bundle_entity = entity_load($bundle_entity_type, $this->entity->bundle()); $bundle_entity->save(); $this->verifyPageCache($referencing_entity_url, 'MISS'); $this->verifyPageCache($listing_url, 'MISS'); $this->verifyPageCache($non_referencing_entity_url, 'HIT'); // Special case: entity types may choose to use their bundle entity type // cache tags, to avoid having excessively granular invalidation. $is_special_case = $bundle_entity->getCacheTags() == $this->entity->getCacheTags() && $bundle_entity->getEntityType()->getListCacheTags() == $this->entity->getEntityType()->getListCacheTags(); if ($is_special_case) { $this->verifyPageCache($empty_entity_listing_url, 'MISS'); $this->verifyPageCache($nonempty_entity_listing_url, 'MISS'); } else { $this->verifyPageCache($empty_entity_listing_url, 'HIT'); $this->verifyPageCache($nonempty_entity_listing_url, 'HIT'); } // Verify cache hits. $this->verifyPageCache($referencing_entity_url, 'HIT'); $this->verifyPageCache($listing_url, 'HIT'); if ($is_special_case) { $this->verifyPageCache($empty_entity_listing_url, 'HIT'); $this->verifyPageCache($nonempty_entity_listing_url, 'HIT'); } } if ($this->entity->getEntityType()->get('field_ui_base_route')) { // Verify that after modifying a configurable field on the entity, there // is a cache miss. $this->pass("Test modification of referenced entity's configurable field.", 'Debug'); $field_storage_name = $this->entity->getEntityTypeId() . '.configurable_field'; $field_storage = FieldStorageConfig::load($field_storage_name); $field_storage->save(); $this->verifyPageCache($referencing_entity_url, 'MISS'); $this->verifyPageCache($listing_url, 'MISS'); $this->verifyPageCache($empty_entity_listing_url, 'HIT'); $this->verifyPageCache($nonempty_entity_listing_url, 'HIT'); $this->verifyPageCache($non_referencing_entity_url, 'HIT'); // Verify cache hits. $this->verifyPageCache($referencing_entity_url, 'HIT'); $this->verifyPageCache($listing_url, 'HIT'); // Verify that after modifying a configurable field on the entity, there // is a cache miss. $this->pass("Test modification of referenced entity's configurable field.", 'Debug'); $field_name = $this->entity->getEntityTypeId() . '.' . $this->entity->bundle() . '.configurable_field'; $field = FieldConfig::load($field_name); $field->save(); $this->verifyPageCache($referencing_entity_url, 'MISS'); $this->verifyPageCache($listing_url, 'MISS'); $this->verifyPageCache($empty_entity_listing_url, 'HIT'); $this->verifyPageCache($nonempty_entity_listing_url, 'HIT'); $this->verifyPageCache($non_referencing_entity_url, 'HIT'); // Verify cache hits. $this->verifyPageCache($referencing_entity_url, 'HIT'); $this->verifyPageCache($listing_url, 'HIT'); } // Verify that after invalidating the entity's cache tag directly, there is // a cache miss for every route except the ones for the non-referencing // entity and the empty entity listing. $this->pass("Test invalidation of referenced entity's cache tag.", 'Debug'); Cache::invalidateTags($this->entity->getCacheTags()); $this->verifyPageCache($referencing_entity_url, 'MISS'); $this->verifyPageCache($listing_url, 'MISS'); $this->verifyPageCache($nonempty_entity_listing_url, 'MISS'); $this->verifyPageCache($non_referencing_entity_url, 'HIT'); $this->verifyPageCache($empty_entity_listing_url, 'HIT'); // Verify cache hits. $this->verifyPageCache($referencing_entity_url, 'HIT'); $this->verifyPageCache($listing_url, 'HIT'); $this->verifyPageCache($nonempty_entity_listing_url, 'HIT'); // Verify that after invalidating the entity's list cache tag directly, // there is a cache miss for both the empty entity listing and the non-empty // entity listing routes, but not for other routes. $this->pass("Test invalidation of referenced entity's list cache tag.", 'Debug'); Cache::invalidateTags($this->entity->getEntityType()->getListCacheTags()); $this->verifyPageCache($empty_entity_listing_url, 'MISS'); $this->verifyPageCache($nonempty_entity_listing_url, 'MISS'); $this->verifyPageCache($referencing_entity_url, 'HIT'); $this->verifyPageCache($non_referencing_entity_url, 'HIT'); $this->verifyPageCache($listing_url, 'HIT'); // Verify cache hits. $this->verifyPageCache($empty_entity_listing_url, 'HIT'); $this->verifyPageCache($nonempty_entity_listing_url, 'HIT'); if (!empty($view_cache_tag)) { // Verify that after invalidating the generic entity type's view cache tag // directly, there is a cache miss for both the referencing entity, and the // listing of referencing entities, but not for other routes. $this->pass("Test invalidation of referenced entity's 'view' cache tag.", 'Debug'); Cache::invalidateTags($view_cache_tag); $this->verifyPageCache($referencing_entity_url, 'MISS'); $this->verifyPageCache($listing_url, 'MISS'); $this->verifyPageCache($non_referencing_entity_url, 'HIT'); $this->verifyPageCache($empty_entity_listing_url, 'HIT'); $this->verifyPageCache($nonempty_entity_listing_url, 'HIT'); // Verify cache hits. $this->verifyPageCache($referencing_entity_url, 'HIT'); $this->verifyPageCache($listing_url, 'HIT'); } // Verify that after deleting the entity, there is a cache miss for every // route except for the non-referencing entity one. $this->pass('Test deletion of referenced entity.', 'Debug'); $this->entity->delete(); $this->verifyPageCache($referencing_entity_url, 'MISS'); $this->verifyPageCache($listing_url, 'MISS'); $this->verifyPageCache($empty_entity_listing_url, 'MISS'); $this->verifyPageCache($nonempty_entity_listing_url, 'MISS'); $this->verifyPageCache($non_referencing_entity_url, 'HIT'); // Verify cache hits. $referencing_entity_cache_tags = Cache::mergeTags($this->referencing_entity->getCacheTags(), \Drupal::entityManager()->getViewBuilder('entity_test')->getCacheTags(), ['rendered']); $this->verifyPageCache($referencing_entity_url, 'HIT', Cache::mergeTags($referencing_entity_cache_tags, $page_cache_tags)); $this->verifyPageCache($listing_url, 'HIT', $page_cache_tags); $this->verifyPageCache($empty_entity_listing_url, 'HIT', $empty_entity_listing_cache_tags); $this->verifyPageCache($nonempty_entity_listing_url, 'HIT', Cache::mergeTags($this->entity->getEntityType()->getListCacheTags(), $this->getAdditionalCacheTagsForEntityListing(), $page_cache_tags)); }
/** * Test the deletion of a field storage. */ function testDelete() { // TODO: Also test deletion of the data stored in the field ? // Create two fields (so we can test that only one is deleted). $field_storage_definition = array('field_name' => 'field_1', 'type' => 'test_field', 'entity_type' => 'entity_test'); FieldStorageConfig::create($field_storage_definition)->save(); $another_field_storage_definition = array('field_name' => 'field_2', 'type' => 'test_field', 'entity_type' => 'entity_test'); FieldStorageConfig::create($another_field_storage_definition)->save(); // Create fields for each. $field_definition = array('field_name' => $field_storage_definition['field_name'], 'entity_type' => 'entity_test', 'bundle' => 'entity_test'); FieldConfig::create($field_definition)->save(); $another_field_definition = $field_definition; $another_field_definition['field_name'] = $another_field_storage_definition['field_name']; FieldConfig::create($another_field_definition)->save(); // Test that the first field is not deleted, and then delete it. $field_storage = current(entity_load_multiple_by_properties('field_storage_config', array('field_name' => $field_storage_definition['field_name'], 'include_deleted' => TRUE))); $this->assertTrue(!empty($field_storage) && !$field_storage->isDeleted(), 'A new storage is not marked for deletion.'); FieldStorageConfig::loadByName('entity_test', $field_storage_definition['field_name'])->delete(); // Make sure that the field is marked as deleted when it is specifically // loaded. $field_storage = current(entity_load_multiple_by_properties('field_storage_config', array('field_name' => $field_storage_definition['field_name'], 'include_deleted' => TRUE))); $this->assertTrue($field_storage->isDeleted(), 'A deleted storage is marked for deletion.'); // Make sure that this field is marked as deleted when it is // specifically loaded. $field = current(entity_load_multiple_by_properties('field_config', array('entity_type' => 'entity_test', 'field_name' => $field_definition['field_name'], 'bundle' => $field_definition['bundle'], 'include_deleted' => TRUE))); $this->assertTrue($field->isDeleted(), 'A field whose storage was deleted is marked for deletion.'); // Try to load the storage normally and make sure it does not show up. $field_storage = FieldStorageConfig::load('entity_test.' . $field_storage_definition['field_name']); $this->assertTrue(empty($field_storage), 'A deleted storage is not loaded by default.'); // Try to load the field normally and make sure it does not show up. $field = FieldConfig::load('entity_test.' . '.' . $field_definition['bundle'] . '.' . $field_definition['field_name']); $this->assertTrue(empty($field), 'A field whose storage was deleted is not loaded by default.'); // Make sure the other field and its storage are not deleted. $another_field_storage = FieldStorageConfig::load('entity_test.' . $another_field_storage_definition['field_name']); $this->assertTrue(!empty($another_field_storage) && !$another_field_storage->isDeleted(), 'A non-deleted storage is not marked for deletion.'); $another_field = FieldConfig::load('entity_test.' . $another_field_definition['bundle'] . '.' . $another_field_definition['field_name']); $this->assertTrue(!empty($another_field) && !$another_field->isDeleted(), 'A field whose storage was not deleted is not marked for deletion.'); // Try to create a new field the same name as a deleted field and // write data into it. FieldStorageConfig::create($field_storage_definition)->save(); FieldConfig::create($field_definition)->save(); $field_storage = FieldStorageConfig::load('entity_test.' . $field_storage_definition['field_name']); $this->assertTrue(!empty($field_storage) && !$field_storage->isDeleted(), 'A new storage with a previously used name is created.'); $field = FieldConfig::load('entity_test.' . $field_definition['bundle'] . '.' . $field_definition['field_name']); $this->assertTrue(!empty($field) && !$field->isDeleted(), 'A new field for a previously used field name is created.'); // Save an entity with data for the field $entity = EntityTest::create(); $values[0]['value'] = mt_rand(1, 127); $entity->{$field_storage->getName()}->value = $values[0]['value']; $entity = $this->entitySaveReload($entity); // Verify the field is present on load $this->assertIdentical(count($entity->{$field_storage->getName()}), count($values), "Data in previously deleted field saves and loads correctly"); foreach ($values as $delta => $value) { $this->assertEqual($entity->{$field_storage->getName()}[$delta]->value, $values[$delta]['value'], "Data in previously deleted field saves and loads correctly"); } }
/** * Tests the Drupal 6 field to Drupal 8 migration. */ public function testFields() { // Text field. /** @var \Drupal\field\Entity\FieldStorageConfig $field_storage */ $field_storage = FieldStorageConfig::load('node.field_test'); $this->assertIdentical('text_long', $field_storage->getType()); // text_long fields do not have settings. $this->assertIdentical([], $field_storage->getSettings()); // Integer field. $field_storage = FieldStorageConfig::load('node.field_test_two'); $this->assertIdentical("integer", $field_storage->getType(), t('Field type is @fieldtype. It should be integer.', array('@fieldtype' => $field_storage->getType()))); // Float field. $field_storage = FieldStorageConfig::load('node.field_test_three'); $this->assertIdentical("decimal", $field_storage->getType(), t('Field type is @fieldtype. It should be decimal.', array('@fieldtype' => $field_storage->getType()))); // Link field. $field_storage = FieldStorageConfig::load('node.field_test_link'); $this->assertIdentical("link", $field_storage->getType(), t('Field type is @fieldtype. It should be link.', array('@fieldtype' => $field_storage->getType()))); // File field. $field_storage = FieldStorageConfig::load('node.field_test_filefield'); $this->assertIdentical("file", $field_storage->getType(), t('Field type is @fieldtype. It should be file.', array('@fieldtype' => $field_storage->getType()))); $field_storage = FieldStorageConfig::load('node.field_test_imagefield'); $this->assertIdentical("image", $field_storage->getType(), t('Field type is @fieldtype. It should be image.', array('@fieldtype' => $field_storage->getType()))); $settings = $field_storage->getSettings(); $this->assertIdentical('file', $settings['target_type']); $this->assertIdentical('public', $settings['uri_scheme']); $this->assertIdentical(array(), array_filter($settings['default_image'])); // Phone field. $field_storage = FieldStorageConfig::load('node.field_test_phone'); $this->assertIdentical("telephone", $field_storage->getType(), t('Field type is @fieldtype. It should be telephone.', array('@fieldtype' => $field_storage->getType()))); // Date field. $field_storage = FieldStorageConfig::load('node.field_test_datetime'); $this->assertIdentical("datetime", $field_storage->getType(), t('Field type is @fieldtype. It should be datetime.', array('@fieldtype' => $field_storage->getType()))); // Decimal field with radio buttons. $field_storage = FieldStorageConfig::load('node.field_test_decimal_radio_buttons'); $this->assertIdentical("list_float", $field_storage->getType(), t('Field type is @fieldtype. It should be list_float.', array('@fieldtype' => $field_storage->getType()))); $this->assertNotNull($field_storage->getSetting('allowed_values')['1.2'], t('First allowed value key is set to 1.2')); $this->assertNotNull($field_storage->getSetting('allowed_values')['2.1'], t('Second allowed value key is set to 2.1')); $this->assertIdentical('1.2', $field_storage->getSetting('allowed_values')['1.2'], t('First allowed value is set to 1.2')); $this->assertIdentical('2.1', $field_storage->getSetting('allowed_values')['2.1'], t('Second allowed value is set to 1.2')); // Float field with a single checkbox. $field_storage = FieldStorageConfig::load('node.field_test_float_single_checkbox'); $this->assertIdentical("boolean", $field_storage->getType(), t('Field type is @fieldtype. It should be boolean.', array('@fieldtype' => $field_storage->getType()))); // Integer field with a select list. $field_storage = FieldStorageConfig::load('node.field_test_integer_selectlist'); $this->assertIdentical("list_integer", $field_storage->getType(), t('Field type is @fieldtype. It should be list_integer.', array('@fieldtype' => $field_storage->getType()))); $this->assertNotNull($field_storage->getSetting('allowed_values')['1234'], t('First allowed value key is set to 1234')); $this->assertNotNull($field_storage->getSetting('allowed_values')['2341'], t('Second allowed value key is set to 2341')); $this->assertNotNull($field_storage->getSetting('allowed_values')['3412'], t('Third allowed value key is set to 3412')); $this->assertNotNull($field_storage->getSetting('allowed_values')['4123'], t('Fourth allowed value key is set to 4123')); $this->assertIdentical('1234', $field_storage->getSetting('allowed_values')['1234'], t('First allowed value is set to 1234')); $this->assertIdentical('2341', $field_storage->getSetting('allowed_values')['2341'], t('Second allowed value is set to 2341')); $this->assertIdentical('3412', $field_storage->getSetting('allowed_values')['3412'], t('Third allowed value is set to 3412')); $this->assertIdentical('4123', $field_storage->getSetting('allowed_values')['4123'], t('Fourth allowed value is set to 4123')); // Text field with a single checkbox. $field_storage = FieldStorageConfig::load('node.field_test_text_single_checkbox'); $this->assertIdentical("boolean", $field_storage->getType(), t('Field type is @fieldtype. It should be boolean.', array('@fieldtype' => $field_storage->getType()))); // Validate that the source count and processed count match up. /** @var \Drupal\migrate\Entity\MigrationInterface $migration */ $migration = Migration::load('d6_field'); $this->assertIdentical($migration->getSourcePlugin()->count(), $migration->getIdMap()->processedCount()); // Check that we've reported on a conflict in widget_types. $messages = []; foreach ($migration->getIdMap()->getMessageIterator() as $message_row) { $messages[] = $message_row->message; } $this->assertIdentical(count($messages), 1); $this->assertIdentical($messages[0], 'Widget types optionwidgets_onoff, text_textfield are used in Drupal 6 field instances: widget type optionwidgets_onoff applied to the Drupal 8 base field'); }
/** * Tests migrating D7 fields to field_storage_config entities. */ public function testFields() { $this->assertEntity('node.body', 'text_with_summary', FALSE, 1); $this->assertEntity('node.field_long_text', 'text_with_summary', FALSE, 1); $this->assertEntity('comment.comment_body', 'text_long', FALSE, 1); $this->assertEntity('node.field_file', 'file', FALSE, 1); $this->assertEntity('user.field_file', 'file', FALSE, 1); $this->assertEntity('node.field_float', 'float', FALSE, 1); $this->assertEntity('node.field_image', 'image', FALSE, 1); $this->assertEntity('node.field_images', 'image', FALSE, 1); $this->assertEntity('node.field_integer', 'integer', FALSE, 1); $this->assertEntity('comment.field_integer', 'integer', FALSE, 1); $this->assertEntity('node.field_integer_list', 'list_integer', FALSE, 1); $this->assertEntity('node.field_link', 'link', FALSE, 1); $this->assertEntity('node.field_tags', 'entity_reference', FALSE, -1); $this->assertEntity('node.field_term_reference', 'entity_reference', FALSE, 1); $this->assertEntity('node.taxonomy_forums', 'entity_reference', FALSE, 1); $this->assertEntity('node.field_text', 'text', FALSE, 1); $this->assertEntity('node.field_text_list', 'list_string', FALSE, 3); $this->assertEntity('node.field_boolean', 'boolean', FALSE, 1); $this->assertEntity('node.field_email', 'email', FALSE, -1); $this->assertEntity('node.field_phone', 'telephone', FALSE, 1); $this->assertEntity('node.field_date', 'datetime', FALSE, 1); $this->assertEntity('node.field_date_with_end_time', 'datetime', FALSE, 1); // Assert that the taxonomy term reference fields are referencing the // correct entity type. $field = FieldStorageConfig::load('node.field_term_reference'); $this->assertIdentical('taxonomy_term', $field->getSetting('target_type')); $field = FieldStorageConfig::load('node.taxonomy_forums'); $this->assertIdentical('taxonomy_term', $field->getSetting('target_type')); }
/** * Test the user picture field migration. */ public function testUserPictureField() { $field_storage = FieldStorageConfig::load('user.user_picture'); $this->assertIdentical('user.user_picture', $field_storage->id()); $this->assertIdentical(array('user', 'user_picture'), entity_load('migration', 'd6_user_picture_field')->getIdMap()->lookupDestinationID(array(''))); }
/** * Tests creating field storages and fields during config import. */ function testImportCreate() { // A field storage with one single field. $field_name = 'field_test_import_sync'; $field_storage_id = "entity_test.{$field_name}"; $field_id = "entity_test.entity_test.{$field_name}"; $field_storage_config_name = "field.storage.{$field_storage_id}"; $field_config_name = "field.field.{$field_id}"; // A field storage with two fields. $field_name_2 = 'field_test_import_sync_2'; $field_storage_id_2 = "entity_test.{$field_name_2}"; $field_id_2a = "entity_test.test_bundle.{$field_name_2}"; $field_id_2b = "entity_test.test_bundle_2.{$field_name_2}"; $field_storage_config_name_2 = "field.storage.{$field_storage_id_2}"; $field_config_name_2a = "field.field.{$field_id_2a}"; $field_config_name_2b = "field.field.{$field_id_2b}"; $active = $this->container->get('config.storage'); $sync = $this->container->get('config.storage.sync'); $this->copyConfig($active, $sync); // Add the new files to the sync directory. $src_dir = __DIR__ . '/../../modules/field_test_config/sync'; $target_dir = config_get_config_directory(CONFIG_SYNC_DIRECTORY); $this->assertTrue(file_unmanaged_copy("{$src_dir}/{$field_storage_config_name}.yml", "{$target_dir}/{$field_storage_config_name}.yml")); $this->assertTrue(file_unmanaged_copy("{$src_dir}/{$field_config_name}.yml", "{$target_dir}/{$field_config_name}.yml")); $this->assertTrue(file_unmanaged_copy("{$src_dir}/{$field_storage_config_name_2}.yml", "{$target_dir}/{$field_storage_config_name_2}.yml")); $this->assertTrue(file_unmanaged_copy("{$src_dir}/{$field_config_name_2a}.yml", "{$target_dir}/{$field_config_name_2a}.yml")); $this->assertTrue(file_unmanaged_copy("{$src_dir}/{$field_config_name_2b}.yml", "{$target_dir}/{$field_config_name_2b}.yml")); // Import the content of the sync directory. $this->configImporter()->import(); // Check that the field and storage were created. $field_storage = FieldStorageConfig::load($field_storage_id); $this->assertTrue($field_storage, 'Test import storage field from sync exists'); $field = FieldConfig::load($field_id); $this->assertTrue($field, 'Test import field from sync exists'); $field_storage = FieldStorageConfig::load($field_storage_id_2); $this->assertTrue($field_storage, 'Test import storage field 2 from sync exists'); $field = FieldConfig::load($field_id_2a); $this->assertTrue($field, 'Test import field 2a from sync exists'); $field = FieldConfig::load($field_id_2b); $this->assertTrue($field, 'Test import field 2b from sync exists'); }
/** * Set the parent id, type and field name to the already created paragraphs. * * @param $sandbox */ function paragraphs_post_update_set_paragraphs_parent_fields(&$sandbox) { // Don't execute the function if paragraphs_update_8003() was already executed // which used to do the same. $module_schema = drupal_get_installed_schema_version('paragraphs'); // The state entry 'paragraphs_update_8003_placeholder' is used in order to // indicate that the placeholder paragraphs_update_8003() function has been // executed, so this function needs to be executed as well. If the non // placeholder version of paragraphs_update_8003() got executed already, the // state won't be set and we skip this update. if ($module_schema >= 8003 && !\Drupal::state()->get('paragraphs_update_8003_placeholder', FALSE)) { return; } if (!isset($sandbox['current_paragraph_field_id'])) { $paragraph_field_ids = []; // Get all the entity reference revisions fields. $map = \Drupal::service('entity_field.manager')->getFieldMapByFieldType('entity_reference_revisions'); foreach ($map as $entity_type_id => $info) { foreach ($info as $name => $data) { if (FieldStorageConfig::loadByName($entity_type_id, $name)->getSetting('target_type') == 'paragraph') { $paragraph_field_ids[] = "{$entity_type_id}.{$name}"; } } } if (!$paragraph_field_ids) { // There are no paragraph fields. Return before initializing the sandbox. return; } // Initialize the sandbox. $sandbox['current_paragraph_field_id'] = 0; $sandbox['paragraph_field_ids'] = $paragraph_field_ids; $sandbox['max'] = count($paragraph_field_ids); $sandbox['progress'] = 0; } /** @var \Drupal\field\FieldStorageConfigInterface $field_storage */ $field_storage = FieldStorageConfig::load($sandbox['paragraph_field_ids'][$sandbox['current_paragraph_field_id']]); // For revisionable entity types, we load and update all revisions. $target_entity_type = \Drupal::entityTypeManager()->getDefinition($field_storage->getTargetEntityTypeId()); if ($target_entity_type->isRevisionable()) { $revision_id = $target_entity_type->getKey('revision'); $entity_ids = \Drupal::entityQuery($field_storage->getTargetEntityTypeId())->condition($field_storage->getName(), NULL, 'IS NOT NULL')->range($sandbox['progress'], Settings::get('paragraph_limit', 50))->allRevisions()->sort($revision_id, 'ASC')->execute(); } else { $id = $target_entity_type->getKey('id'); $entity_ids = \Drupal::entityQuery($field_storage->getTargetEntityTypeId())->condition($field_storage->getName(), NULL, 'IS NOT NULL')->range($sandbox['progress'], Settings::get('paragraph_limit', 50))->sort($id, 'ASC')->execute(); } foreach ($entity_ids as $revision_id => $entity_id) { // For revisionable entity types, we load a specific revision otherwise load // the entity. if ($target_entity_type->isRevisionable()) { $host_entity = \Drupal::entityTypeManager()->getStorage($field_storage->getTargetEntityTypeId())->loadRevision($revision_id); } else { $host_entity = \Drupal::entityTypeManager()->getStorage($field_storage->getTargetEntityTypeId())->load($entity_id); } foreach ($host_entity->get($field_storage->getName()) as $field_item) { // Skip broken and already updated references (e.g. Nested paragraphs). if ($field_item->entity && empty($field_item->entity->parent_type->value)) { // Set the parent fields and save, ensure that no new revision is // created. $field_item->entity->parent_type = $field_storage->getTargetEntityTypeId(); $field_item->entity->parent_id = $host_entity->id(); $field_item->entity->parent_field_name = $field_storage->getName(); $field_item->entity->setNewRevision(FALSE); $field_item->entity->save(); } } } // Continue with the next paragraph_field_id when the loaded entities are less // than paragraph_limit. if (count($entity_ids) < Settings::get('paragraph_limit', 50)) { $sandbox['current_paragraph_field_id']++; $sandbox['progress'] = 0; } else { $sandbox['progress'] += Settings::get('paragraph_limit', 50); } // Update #finished, 1 if the the whole update has finished. $sandbox['#finished'] = empty($sandbox['max']) ? 1 : $sandbox['current_paragraph_field_id'] / $sandbox['max']; }
/** * Tests comment variables migrated into a field entity. */ public function testCommentField() { $this->assertTrue(is_object(FieldStorageConfig::load('node.comment'))); }
/** * Tests the Drupal 6 upload settings to Drupal 8 field migration. */ public function testUpload() { $field_storage = FieldStorageConfig::load('node.upload'); $this->assertIdentical('node.upload', $field_storage->id()); $this->assertIdentical(array('node', 'upload'), $this->getMigration('d6_upload_field')->getIdMap()->lookupDestinationID(array(''))); }
/** * Tests cache tags presence and invalidation of the entity at its URI. * * Tests the following cache tags: * - "<entity type>_view" * - "<entity_type>:<entity ID>" */ public function testEntityUri() { $entity_url = $this->entity->urlInfo(); $entity_type = $this->entity->getEntityTypeId(); // Selects the view mode that will be used. $view_mode = $this->selectViewMode($entity_type); // The default cache contexts for rendered entities. $entity_cache_contexts = ['languages:' . LanguageInterface::TYPE_INTERFACE, 'theme', 'user.permissions']; // Generate the standardized entity cache tags. $cache_tag = $this->entity->getCacheTags(); $view_cache_tag = \Drupal::entityManager()->getViewBuilder($entity_type)->getCacheTags(); $render_cache_tag = 'rendered'; $this->pass("Test entity.", 'Debug'); $this->verifyPageCache($entity_url, 'MISS'); // Verify a cache hit, but also the presence of the correct cache tags. $this->verifyPageCache($entity_url, 'HIT'); // Also verify the existence of an entity render cache entry, if this entity // type supports render caching. if (\Drupal::entityManager()->getDefinition($entity_type)->isRenderCacheable()) { $cache_keys = ['entity_view', $entity_type, $this->entity->id(), $view_mode]; $cid = $this->createCacheId($cache_keys, $entity_cache_contexts); $redirected_cid = NULL; $additional_cache_contexts = $this->getAdditionalCacheContextsForEntity($this->entity); if (count($additional_cache_contexts)) { $redirected_cid = $this->createCacheId($cache_keys, Cache::mergeContexts($entity_cache_contexts, $additional_cache_contexts)); } $expected_cache_tags = Cache::mergeTags($cache_tag, $view_cache_tag); $expected_cache_tags = Cache::mergeTags($expected_cache_tags, $this->getAdditionalCacheTagsForEntity($this->entity)); $expected_cache_tags = Cache::mergeTags($expected_cache_tags, array($render_cache_tag)); $this->verifyRenderCache($cid, $expected_cache_tags, $redirected_cid); } // Verify that after modifying the entity, there is a cache miss. $this->pass("Test modification of entity.", 'Debug'); $this->entity->save(); $this->verifyPageCache($entity_url, 'MISS'); // Verify a cache hit. $this->verifyPageCache($entity_url, 'HIT'); // Verify that after modifying the entity's display, there is a cache miss. $this->pass("Test modification of entity's '{$view_mode}' display.", 'Debug'); $entity_display = entity_get_display($entity_type, $this->entity->bundle(), $view_mode); $entity_display->save(); $this->verifyPageCache($entity_url, 'MISS'); // Verify a cache hit. $this->verifyPageCache($entity_url, 'HIT'); if ($bundle_entity_type_id = $this->entity->getEntityType()->getBundleEntityType()) { // Verify that after modifying the corresponding bundle entity, there is a // cache miss. $this->pass("Test modification of entity's bundle entity.", 'Debug'); $bundle_entity = entity_load($bundle_entity_type_id, $this->entity->bundle()); $bundle_entity->save(); $this->verifyPageCache($entity_url, 'MISS'); // Verify a cache hit. $this->verifyPageCache($entity_url, 'HIT'); } if ($this->entity->getEntityType()->get('field_ui_base_route')) { // Verify that after modifying a configurable field on the entity, there // is a cache miss. $this->pass("Test modification of entity's configurable field.", 'Debug'); $field_storage_name = $this->entity->getEntityTypeId() . '.configurable_field'; $field_storage = FieldStorageConfig::load($field_storage_name); $field_storage->save(); $this->verifyPageCache($entity_url, 'MISS'); // Verify a cache hit. $this->verifyPageCache($entity_url, 'HIT'); // Verify that after modifying a configurable field on the entity, there // is a cache miss. $this->pass("Test modification of entity's configurable field.", 'Debug'); $field_name = $this->entity->getEntityTypeId() . '.' . $this->entity->bundle() . '.configurable_field'; $field = FieldConfig::load($field_name); $field->save(); $this->verifyPageCache($entity_url, 'MISS'); // Verify a cache hit. $this->verifyPageCache($entity_url, 'HIT'); } // Verify that after invalidating the entity's cache tag directly, there is // a cache miss. $this->pass("Test invalidation of entity's cache tag.", 'Debug'); Cache::invalidateTags($this->entity->getCacheTagsToInvalidate()); $this->verifyPageCache($entity_url, 'MISS'); // Verify a cache hit. $this->verifyPageCache($entity_url, 'HIT'); // Verify that after invalidating the generic entity type's view cache tag // directly, there is a cache miss. $this->pass("Test invalidation of entity's 'view' cache tag.", 'Debug'); Cache::invalidateTags($view_cache_tag); $this->verifyPageCache($entity_url, 'MISS'); // Verify a cache hit. $this->verifyPageCache($entity_url, 'HIT'); // Verify that after deleting the entity, there is a cache miss. $this->pass('Test deletion of entity.', 'Debug'); $this->entity->delete(); $this->verifyPageCache($entity_url, 'MISS'); $this->assertResponse(404); }
/** * Tests creating field storages and fields during config import. */ function testImportCreate() { // A field storage with one single field. $field_name = 'field_test_import_staging'; $field_storage_id = "entity_test.{$field_name}"; $field_id = "entity_test.entity_test.{$field_name}"; $field_storage_config_name = "field.storage.{$field_storage_id}"; $field_config_name = "field.field.{$field_id}"; // A field storage with two fields. $field_name_2 = 'field_test_import_staging_2'; $field_storage_id_2 = "entity_test.{$field_name_2}"; $field_id_2a = "entity_test.test_bundle.{$field_name_2}"; $field_id_2b = "entity_test.test_bundle_2.{$field_name_2}"; $field_storage_config_name_2 = "field.storage.{$field_storage_id_2}"; $field_config_name_2a = "field.field.{$field_id_2a}"; $field_config_name_2b = "field.field.{$field_id_2b}"; $active = $this->container->get('config.storage'); $staging = $this->container->get('config.storage.staging'); $this->copyConfig($active, $staging); // Add the new files to the staging directory. $src_dir = drupal_get_path('module', 'field_test_config') . '/staging'; $target_dir = $this->configDirectories[CONFIG_STAGING_DIRECTORY]; $this->assertTrue(file_unmanaged_copy("{$src_dir}/{$field_storage_config_name}.yml", "{$target_dir}/{$field_storage_config_name}.yml")); $this->assertTrue(file_unmanaged_copy("{$src_dir}/{$field_config_name}.yml", "{$target_dir}/{$field_config_name}.yml")); $this->assertTrue(file_unmanaged_copy("{$src_dir}/{$field_storage_config_name_2}.yml", "{$target_dir}/{$field_storage_config_name_2}.yml")); $this->assertTrue(file_unmanaged_copy("{$src_dir}/{$field_config_name_2a}.yml", "{$target_dir}/{$field_config_name_2a}.yml")); $this->assertTrue(file_unmanaged_copy("{$src_dir}/{$field_config_name_2b}.yml", "{$target_dir}/{$field_config_name_2b}.yml")); // Import the content of the staging directory. $this->configImporter()->import(); // Check that the field and storage were created. $field_storage = FieldStorageConfig::load($field_storage_id); $this->assertTrue($field_storage, 'Test import storage field from staging exists'); $field = FieldConfig::load($field_id); $this->assertTrue($field, 'Test import field from staging exists'); $field_storage = FieldStorageConfig::load($field_storage_id_2); $this->assertTrue($field_storage, 'Test import storage field 2 from staging exists'); $field = FieldConfig::load($field_id_2a); $this->assertTrue($field, 'Test import field 2a from staging exists'); $field = FieldConfig::load($field_id_2b); $this->assertTrue($field, 'Test import field 2b from staging exists'); }
/** * Tests migrating D7 fields to field_storage_config entities. */ public function testFields() { $this->assertEntity('node.body', 'text_with_summary', FALSE, 1); $this->assertEntity('node.field_long_text', 'text_with_summary', FALSE, 1); $this->assertEntity('comment.comment_body', 'text_long', FALSE, 1); $this->assertEntity('node.field_file', 'file', FALSE, 1); $this->assertEntity('user.field_file', 'file', FALSE, 1); $this->assertEntity('node.field_float', 'float', FALSE, 1); $this->assertEntity('node.field_image', 'image', FALSE, 1); $this->assertEntity('node.field_images', 'image', FALSE, 1); $this->assertEntity('node.field_integer', 'integer', FALSE, 1); $this->assertEntity('comment.field_integer', 'integer', FALSE, 1); $this->assertEntity('node.field_integer_list', 'list_integer', FALSE, 1); $this->assertEntity('node.field_link', 'link', FALSE, 1); $this->assertEntity('node.field_tags', 'entity_reference', FALSE, -1); $this->assertEntity('node.field_term_reference', 'entity_reference', FALSE, 1); $this->assertEntity('node.taxonomy_forums', 'entity_reference', FALSE, 1); $this->assertEntity('node.field_text', 'text', FALSE, 1); $this->assertEntity('node.field_text_list', 'list_string', FALSE, 3); $this->assertEntity('node.field_boolean', 'boolean', FALSE, 1); $this->assertEntity('node.field_email', 'email', FALSE, -1); $this->assertEntity('node.field_phone', 'telephone', FALSE, 1); $this->assertEntity('node.field_date', 'datetime', FALSE, 1); $this->assertEntity('node.field_date_with_end_time', 'datetime', FALSE, 1); // Assert that the taxonomy term reference fields are referencing the // correct entity type. $field = FieldStorageConfig::load('node.field_term_reference'); $this->assertIdentical('taxonomy_term', $field->getSetting('target_type')); $field = FieldStorageConfig::load('node.taxonomy_forums'); $this->assertIdentical('taxonomy_term', $field->getSetting('target_type')); // Validate that the source count and processed count match up. /** @var \Drupal\migrate\Plugin\MigrationInterface $migration */ $migration = $this->getMigration('d7_field'); $this->assertIdentical($migration->getSourcePlugin()->count(), $migration->getIdMap()->processedCount()); }
/** * Tests cache tags presence and invalidation of the entity when referenced. * * Tests the following cache tags: * - entity type view cache tag: "<entity type>_view" * - entity cache tag: "<entity type>:<entity ID>" * - entity type list cache tag: "<entity type>_list" * - referencing entity type view cache tag: "<referencing entity type>_view" * - referencing entity type cache tag: "<referencing entity type>:<referencing entity ID>" */ public function testReferencedEntity() { $entity_type = $this->entity->getEntityTypeId(); $referencing_entity_url = $this->referencingEntity->urlInfo('canonical'); $non_referencing_entity_url = $this->nonReferencingEntity->urlInfo('canonical'); $listing_url = Url::fromRoute('entity.entity_test.collection_referencing_entities', ['entity_reference_field_name' => $entity_type . '_reference', 'referenced_entity_type' => $entity_type, 'referenced_entity_id' => $this->entity->id()]); $empty_entity_listing_url = Url::fromRoute('entity.entity_test.collection_empty', ['entity_type_id' => $entity_type]); $nonempty_entity_listing_url = Url::fromRoute('entity.entity_test.collection_labels_alphabetically', ['entity_type_id' => $entity_type]); // The default cache contexts for rendered entities. $default_cache_contexts = ['languages:' . LanguageInterface::TYPE_INTERFACE, 'theme', 'user.permissions']; $entity_cache_contexts = $default_cache_contexts; $page_cache_contexts = Cache::mergeContexts($default_cache_contexts, ['url.query_args:' . MainContentViewSubscriber::WRAPPER_FORMAT]); // Cache tags present on every rendered page. // 'user.permissions' is a required cache context, and responses that vary // by this cache context when requested by anonymous users automatically // also get this cache tag, to ensure correct invalidation. $page_cache_tags = Cache::mergeTags(['rendered'], ['config:user.role.anonymous']); // If the block module is used, the Block page display variant is used, // which adds the block config entity type's list cache tags. $page_cache_tags = Cache::mergeTags($page_cache_tags, \Drupal::moduleHandler()->moduleExists('block') ? ['config:block_list'] : []); $page_cache_tags_referencing_entity = in_array('user.permissions', $this->getAccessCacheContextsForEntity($this->referencingEntity)) ? ['config:user.role.anonymous'] : []; $view_cache_tag = array(); if ($this->entity->getEntityType()->hasHandlerClass('view_builder')) { $view_cache_tag = \Drupal::entityManager()->getViewBuilder($entity_type)->getCacheTags(); } $context_metadata = \Drupal::service('cache_contexts_manager')->convertTokensToKeys($entity_cache_contexts); $cache_context_tags = $context_metadata->getCacheTags(); // Generate the cache tags for the (non) referencing entities. $referencing_entity_cache_tags = Cache::mergeTags($this->referencingEntity->getCacheTags(), \Drupal::entityManager()->getViewBuilder('entity_test')->getCacheTags()); // Includes the main entity's cache tags, since this entity references it. $referencing_entity_cache_tags = Cache::mergeTags($referencing_entity_cache_tags, $this->entity->getCacheTags()); $referencing_entity_cache_tags = Cache::mergeTags($referencing_entity_cache_tags, $this->getAdditionalCacheTagsForEntity($this->entity)); $referencing_entity_cache_tags = Cache::mergeTags($referencing_entity_cache_tags, $view_cache_tag); $referencing_entity_cache_tags = Cache::mergeTags($referencing_entity_cache_tags, $cache_context_tags); $referencing_entity_cache_tags = Cache::mergeTags($referencing_entity_cache_tags, ['rendered']); $non_referencing_entity_cache_tags = Cache::mergeTags($this->nonReferencingEntity->getCacheTags(), \Drupal::entityManager()->getViewBuilder('entity_test')->getCacheTags()); $non_referencing_entity_cache_tags = Cache::mergeTags($non_referencing_entity_cache_tags, ['rendered']); // Generate the cache tags for all two possible entity listing paths. // 1. list cache tag only (listing query has no match) // 2. list cache tag plus entity cache tag (listing query has a match) $empty_entity_listing_cache_tags = Cache::mergeTags($this->entity->getEntityType()->getListCacheTags(), $page_cache_tags); $nonempty_entity_listing_cache_tags = Cache::mergeTags($this->entity->getEntityType()->getListCacheTags(), $this->entity->getCacheTags()); $nonempty_entity_listing_cache_tags = Cache::mergeTags($nonempty_entity_listing_cache_tags, $this->getAdditionalCacheTagsForEntityListing($this->entity)); $nonempty_entity_listing_cache_tags = Cache::mergeTags($nonempty_entity_listing_cache_tags, $page_cache_tags); $this->pass("Test referencing entity.", 'Debug'); $this->verifyPageCache($referencing_entity_url, 'MISS'); // Verify a cache hit, but also the presence of the correct cache tags. $expected_tags = Cache::mergeTags($referencing_entity_cache_tags, $page_cache_tags); $expected_tags = Cache::mergeTags($expected_tags, $page_cache_tags_referencing_entity); $this->verifyPageCache($referencing_entity_url, 'HIT', $expected_tags); // Also verify the existence of an entity render cache entry. $cache_keys = ['entity_view', 'entity_test', $this->referencingEntity->id(), 'full']; $cid = $this->createCacheId($cache_keys, $entity_cache_contexts); $access_cache_contexts = $this->getAccessCacheContextsForEntity($this->entity); $additional_cache_contexts = $this->getAdditionalCacheContextsForEntity($this->referencingEntity); $redirected_cid = NULL; if (count($access_cache_contexts) || count($additional_cache_contexts)) { $cache_contexts = Cache::mergeContexts($entity_cache_contexts, $additional_cache_contexts); $cache_contexts = Cache::mergeContexts($cache_contexts, $access_cache_contexts); $redirected_cid = $this->createCacheId($cache_keys, $cache_contexts); $context_metadata = \Drupal::service('cache_contexts_manager')->convertTokensToKeys($cache_contexts); $referencing_entity_cache_tags = Cache::mergeTags($referencing_entity_cache_tags, $context_metadata->getCacheTags()); } $this->verifyRenderCache($cid, $referencing_entity_cache_tags, $redirected_cid); $this->pass("Test non-referencing entity.", 'Debug'); $this->verifyPageCache($non_referencing_entity_url, 'MISS'); // Verify a cache hit, but also the presence of the correct cache tags. $this->verifyPageCache($non_referencing_entity_url, 'HIT', Cache::mergeTags($non_referencing_entity_cache_tags, $page_cache_tags)); // Also verify the existence of an entity render cache entry. $cache_keys = ['entity_view', 'entity_test', $this->nonReferencingEntity->id(), 'full']; $cid = $this->createCacheId($cache_keys, $entity_cache_contexts); $this->verifyRenderCache($cid, $non_referencing_entity_cache_tags); $this->pass("Test listing of referencing entities.", 'Debug'); // Prime the page cache for the listing of referencing entities. $this->verifyPageCache($listing_url, 'MISS'); // Verify a cache hit, but also the presence of the correct cache tags. $expected_tags = Cache::mergeTags($referencing_entity_cache_tags, $page_cache_tags); $expected_tags = Cache::mergeTags($expected_tags, $page_cache_tags_referencing_entity); $this->verifyPageCache($listing_url, 'HIT', $expected_tags); $this->pass("Test empty listing.", 'Debug'); // Prime the page cache for the empty listing. $this->verifyPageCache($empty_entity_listing_url, 'MISS'); // Verify a cache hit, but also the presence of the correct cache tags. $this->verifyPageCache($empty_entity_listing_url, 'HIT', $empty_entity_listing_cache_tags); // Verify the entity type's list cache contexts are present. $contexts_in_header = $this->drupalGetHeader('X-Drupal-Cache-Contexts'); $this->assertEqual(Cache::mergeContexts($page_cache_contexts, $this->getAdditionalCacheContextsForEntityListing()), empty($contexts_in_header) ? [] : explode(' ', $contexts_in_header)); $this->pass("Test listing containing referenced entity.", 'Debug'); // Prime the page cache for the listing containing the referenced entity. $this->verifyPageCache($nonempty_entity_listing_url, 'MISS', $nonempty_entity_listing_cache_tags); // Verify a cache hit, but also the presence of the correct cache tags. $this->verifyPageCache($nonempty_entity_listing_url, 'HIT', $nonempty_entity_listing_cache_tags); // Verify the entity type's list cache contexts are present. $contexts_in_header = $this->drupalGetHeader('X-Drupal-Cache-Contexts'); $this->assertEqual(Cache::mergeContexts($page_cache_contexts, $this->getAdditionalCacheContextsForEntityListing()), empty($contexts_in_header) ? [] : explode(' ', $contexts_in_header)); // Verify that after modifying the referenced entity, there is a cache miss // for every route except the one for the non-referencing entity. $this->pass("Test modification of referenced entity.", 'Debug'); $this->entity->save(); $this->verifyPageCache($referencing_entity_url, 'MISS'); $this->verifyPageCache($listing_url, 'MISS'); $this->verifyPageCache($empty_entity_listing_url, 'MISS'); $this->verifyPageCache($nonempty_entity_listing_url, 'MISS'); $this->verifyPageCache($non_referencing_entity_url, 'HIT'); // Verify cache hits. $this->verifyPageCache($referencing_entity_url, 'HIT'); $this->verifyPageCache($listing_url, 'HIT'); $this->verifyPageCache($empty_entity_listing_url, 'HIT'); $this->verifyPageCache($nonempty_entity_listing_url, 'HIT'); // Verify that after modifying the referencing entity, there is a cache miss // for every route except the ones for the non-referencing entity and the // empty entity listing. $this->pass("Test modification of referencing entity.", 'Debug'); $this->referencingEntity->save(); $this->verifyPageCache($referencing_entity_url, 'MISS'); $this->verifyPageCache($listing_url, 'MISS'); $this->verifyPageCache($nonempty_entity_listing_url, 'HIT'); $this->verifyPageCache($non_referencing_entity_url, 'HIT'); $this->verifyPageCache($empty_entity_listing_url, 'HIT'); // Verify cache hits. $this->verifyPageCache($referencing_entity_url, 'HIT'); $this->verifyPageCache($listing_url, 'HIT'); $this->verifyPageCache($nonempty_entity_listing_url, 'HIT'); // Verify that after modifying the non-referencing entity, there is a cache // miss only for the non-referencing entity route. $this->pass("Test modification of non-referencing entity.", 'Debug'); $this->nonReferencingEntity->save(); $this->verifyPageCache($referencing_entity_url, 'HIT'); $this->verifyPageCache($listing_url, 'HIT'); $this->verifyPageCache($empty_entity_listing_url, 'HIT'); $this->verifyPageCache($nonempty_entity_listing_url, 'HIT'); $this->verifyPageCache($non_referencing_entity_url, 'MISS'); // Verify cache hits. $this->verifyPageCache($non_referencing_entity_url, 'HIT'); if ($this->entity->getEntityType()->hasHandlerClass('view_builder')) { // Verify that after modifying the entity's display, there is a cache miss // for both the referencing entity, and the listing of referencing // entities, but not for any other routes. $referenced_entity_view_mode = $this->selectViewMode($this->entity->getEntityTypeId()); $this->pass("Test modification of referenced entity's '{$referenced_entity_view_mode}' display.", 'Debug'); $entity_display = entity_get_display($entity_type, $this->entity->bundle(), $referenced_entity_view_mode); $entity_display->save(); $this->verifyPageCache($referencing_entity_url, 'MISS'); $this->verifyPageCache($listing_url, 'MISS'); $this->verifyPageCache($non_referencing_entity_url, 'HIT'); $this->verifyPageCache($empty_entity_listing_url, 'HIT'); $this->verifyPageCache($nonempty_entity_listing_url, 'HIT'); // Verify cache hits. $this->verifyPageCache($referencing_entity_url, 'HIT'); $this->verifyPageCache($listing_url, 'HIT'); } if ($bundle_entity_type_id = $this->entity->getEntityType()->getBundleEntityType()) { // Verify that after modifying the corresponding bundle entity, there is a // cache miss for both the referencing entity, and the listing of // referencing entities, but not for any other routes. $this->pass("Test modification of referenced entity's bundle entity.", 'Debug'); $bundle_entity = entity_load($bundle_entity_type_id, $this->entity->bundle()); $bundle_entity->save(); $this->verifyPageCache($referencing_entity_url, 'MISS'); $this->verifyPageCache($listing_url, 'MISS'); $this->verifyPageCache($non_referencing_entity_url, 'HIT'); // Special case: entity types may choose to use their bundle entity type // cache tags, to avoid having excessively granular invalidation. $is_special_case = $bundle_entity->getCacheTags() == $this->entity->getCacheTags() && $bundle_entity->getEntityType()->getListCacheTags() == $this->entity->getEntityType()->getListCacheTags(); if ($is_special_case) { $this->verifyPageCache($empty_entity_listing_url, 'MISS'); $this->verifyPageCache($nonempty_entity_listing_url, 'MISS'); } else { $this->verifyPageCache($empty_entity_listing_url, 'HIT'); $this->verifyPageCache($nonempty_entity_listing_url, 'HIT'); } // Verify cache hits. $this->verifyPageCache($referencing_entity_url, 'HIT'); $this->verifyPageCache($listing_url, 'HIT'); if ($is_special_case) { $this->verifyPageCache($empty_entity_listing_url, 'HIT'); $this->verifyPageCache($nonempty_entity_listing_url, 'HIT'); } } if ($this->entity->getEntityType()->get('field_ui_base_route')) { // Verify that after modifying a configurable field on the entity, there // is a cache miss. $this->pass("Test modification of referenced entity's configurable field.", 'Debug'); $field_storage_name = $this->entity->getEntityTypeId() . '.configurable_field'; $field_storage = FieldStorageConfig::load($field_storage_name); $field_storage->save(); $this->verifyPageCache($referencing_entity_url, 'MISS'); $this->verifyPageCache($listing_url, 'MISS'); $this->verifyPageCache($empty_entity_listing_url, 'HIT'); $this->verifyPageCache($nonempty_entity_listing_url, 'HIT'); $this->verifyPageCache($non_referencing_entity_url, 'HIT'); // Verify cache hits. $this->verifyPageCache($referencing_entity_url, 'HIT'); $this->verifyPageCache($listing_url, 'HIT'); // Verify that after modifying a configurable field on the entity, there // is a cache miss. $this->pass("Test modification of referenced entity's configurable field.", 'Debug'); $field_name = $this->entity->getEntityTypeId() . '.' . $this->entity->bundle() . '.configurable_field'; $field = FieldConfig::load($field_name); $field->save(); $this->verifyPageCache($referencing_entity_url, 'MISS'); $this->verifyPageCache($listing_url, 'MISS'); $this->verifyPageCache($empty_entity_listing_url, 'HIT'); $this->verifyPageCache($nonempty_entity_listing_url, 'HIT'); $this->verifyPageCache($non_referencing_entity_url, 'HIT'); // Verify cache hits. $this->verifyPageCache($referencing_entity_url, 'HIT'); $this->verifyPageCache($listing_url, 'HIT'); } // Verify that after invalidating the entity's cache tag directly, there is // a cache miss for every route except the ones for the non-referencing // entity and the empty entity listing. $this->pass("Test invalidation of referenced entity's cache tag.", 'Debug'); Cache::invalidateTags($this->entity->getCacheTagsToInvalidate()); $this->verifyPageCache($referencing_entity_url, 'MISS'); $this->verifyPageCache($listing_url, 'MISS'); $this->verifyPageCache($nonempty_entity_listing_url, 'MISS'); $this->verifyPageCache($non_referencing_entity_url, 'HIT'); $this->verifyPageCache($empty_entity_listing_url, 'HIT'); // Verify cache hits. $this->verifyPageCache($referencing_entity_url, 'HIT'); $this->verifyPageCache($listing_url, 'HIT'); $this->verifyPageCache($nonempty_entity_listing_url, 'HIT'); // Verify that after invalidating the entity's list cache tag directly, // there is a cache miss for both the empty entity listing and the non-empty // entity listing routes, but not for other routes. $this->pass("Test invalidation of referenced entity's list cache tag.", 'Debug'); Cache::invalidateTags($this->entity->getEntityType()->getListCacheTags()); $this->verifyPageCache($empty_entity_listing_url, 'MISS'); $this->verifyPageCache($nonempty_entity_listing_url, 'MISS'); $this->verifyPageCache($referencing_entity_url, 'HIT'); $this->verifyPageCache($non_referencing_entity_url, 'HIT'); $this->verifyPageCache($listing_url, 'HIT'); // Verify cache hits. $this->verifyPageCache($empty_entity_listing_url, 'HIT'); $this->verifyPageCache($nonempty_entity_listing_url, 'HIT'); if (!empty($view_cache_tag)) { // Verify that after invalidating the generic entity type's view cache tag // directly, there is a cache miss for both the referencing entity, and the // listing of referencing entities, but not for other routes. $this->pass("Test invalidation of referenced entity's 'view' cache tag.", 'Debug'); Cache::invalidateTags($view_cache_tag); $this->verifyPageCache($referencing_entity_url, 'MISS'); $this->verifyPageCache($listing_url, 'MISS'); $this->verifyPageCache($non_referencing_entity_url, 'HIT'); $this->verifyPageCache($empty_entity_listing_url, 'HIT'); $this->verifyPageCache($nonempty_entity_listing_url, 'HIT'); // Verify cache hits. $this->verifyPageCache($referencing_entity_url, 'HIT'); $this->verifyPageCache($listing_url, 'HIT'); } // Verify that after deleting the entity, there is a cache miss for every // route except for the non-referencing entity one. $this->pass('Test deletion of referenced entity.', 'Debug'); $this->entity->delete(); $this->verifyPageCache($referencing_entity_url, 'MISS'); $this->verifyPageCache($listing_url, 'MISS'); $this->verifyPageCache($empty_entity_listing_url, 'MISS'); $this->verifyPageCache($nonempty_entity_listing_url, 'MISS'); $this->verifyPageCache($non_referencing_entity_url, 'HIT'); // Verify cache hits. $referencing_entity_cache_tags = Cache::mergeTags($this->referencingEntity->getCacheTags(), \Drupal::entityManager()->getViewBuilder('entity_test')->getCacheTags()); $referencing_entity_cache_tags = Cache::mergeTags($referencing_entity_cache_tags, ['rendered']); $nonempty_entity_listing_cache_tags = Cache::mergeTags($this->entity->getEntityType()->getListCacheTags(), $this->getAdditionalCacheTagsForEntityListing()); $nonempty_entity_listing_cache_tags = Cache::mergeTags($nonempty_entity_listing_cache_tags, $page_cache_tags); $this->verifyPageCache($referencing_entity_url, 'HIT', Cache::mergeTags($referencing_entity_cache_tags, $page_cache_tags)); $this->verifyPageCache($listing_url, 'HIT', $page_cache_tags); $this->verifyPageCache($empty_entity_listing_url, 'HIT', $empty_entity_listing_cache_tags); $this->verifyPageCache($nonempty_entity_listing_url, 'HIT', $nonempty_entity_listing_cache_tags); }
/** * Tests deleting field storages and fields as part of config import. */ public function testImportDelete() { $this->installConfig(['field_test_config']); // At this point there are 5 field configuration objects in the active // storage. // - field.storage.entity_test.field_test_import // - field.storage.entity_test.field_test_import_2 // - field.field.entity_test.entity_test.field_test_import // - field.field.entity_test.entity_test.field_test_import_2 // - field.field.entity_test.test_bundle.field_test_import_2 $field_name = 'field_test_import'; $field_storage_id = "entity_test.{$field_name}"; $field_name_2 = 'field_test_import_2'; $field_storage_id_2 = "entity_test.{$field_name_2}"; $field_id = "entity_test.entity_test.{$field_name}"; $field_id_2a = "entity_test.entity_test.{$field_name_2}"; $field_id_2b = "entity_test.test_bundle.{$field_name_2}"; $field_storage_config_name = "field.storage.{$field_storage_id}"; $field_storage_config_name_2 = "field.storage.{$field_storage_id_2}"; $field_config_name = "field.field.{$field_id}"; $field_config_name_2a = "field.field.{$field_id_2a}"; $field_config_name_2b = "field.field.{$field_id_2b}"; // Create a second bundle for the 'Entity test' entity type. entity_test_create_bundle('test_bundle'); // Get the uuid's for the field storages. $field_storage_uuid = FieldStorageConfig::load($field_storage_id)->uuid(); $field_storage_uuid_2 = FieldStorageConfig::load($field_storage_id_2)->uuid(); $active = $this->container->get('config.storage'); $staging = $this->container->get('config.storage.staging'); $this->copyConfig($active, $staging); $this->assertTrue($staging->delete($field_storage_config_name), String::format('Deleted field storage: !field_storage', array('!field_storage' => $field_storage_config_name))); $this->assertTrue($staging->delete($field_storage_config_name_2), String::format('Deleted field storage: !field_storage', array('!field_storage' => $field_storage_config_name_2))); $this->assertTrue($staging->delete($field_config_name), String::format('Deleted field: !field', array('!field' => $field_config_name))); $this->assertTrue($staging->delete($field_config_name_2a), String::format('Deleted field: !field', array('!field' => $field_config_name_2a))); $this->assertTrue($staging->delete($field_config_name_2b), String::format('Deleted field: !field', array('!field' => $field_config_name_2b))); $deletes = $this->configImporter()->getUnprocessedConfiguration('delete'); $this->assertEqual(count($deletes), 5, 'Importing configuration will delete 3 fields and 2 field storages.'); // Import the content of the staging directory. $this->configImporter()->import(); // Check that the field storages and fields are gone. \Drupal::entityManager()->getStorage('field_storage_config')->resetCache(array($field_storage_id)); $field_storage = FieldStorageConfig::load($field_storage_id); $this->assertFalse($field_storage, 'The field storage was deleted.'); \Drupal::entityManager()->getStorage('field_storage_config')->resetCache(array($field_storage_id_2)); $field_storage_2 = FieldStorageConfig::load($field_storage_id_2); $this->assertFalse($field_storage_2, 'The second field storage was deleted.'); \Drupal::entityManager()->getStorage('field_config')->resetCache(array($field_id)); $field = FieldConfig::load($field_id); $this->assertFalse($field, 'The field was deleted.'); \Drupal::entityManager()->getStorage('field_config')->resetCache(array($field_id_2a)); $field_2a = FieldConfig::load($field_id_2a); $this->assertFalse($field_2a, 'The second field on test bundle was deleted.'); \Drupal::entityManager()->getStorage('field_config')->resetCache(array($field_id_2b)); $field_2b = FieldConfig::load($field_id_2b); $this->assertFalse($field_2b, 'The second field on test bundle 2 was deleted.'); // Check that all config files are gone. $active = $this->container->get('config.storage'); $this->assertIdentical($active->listAll($field_storage_config_name), array()); $this->assertIdentical($active->listAll($field_storage_config_name_2), array()); $this->assertIdentical($active->listAll($field_config_name), array()); $this->assertIdentical($active->listAll($field_config_name_2a), array()); $this->assertIdentical($active->listAll($field_config_name_2b), array()); // Check that the storage definition is preserved in state. $deleted_storages = \Drupal::state()->get('field.storage.deleted') ?: array(); $this->assertTrue(isset($deleted_storages[$field_storage_uuid])); $this->assertTrue(isset($deleted_storages[$field_storage_uuid_2])); // Purge field data, and check that the storage definition has been // completely removed once the data is purged. field_purge_batch(10); $deleted_storages = \Drupal::state()->get('field.storage.deleted') ?: array(); $this->assertTrue(empty($deleted_storages), 'Fields are deleted'); }
/** * Tests support for cardinality > 1 for entity reference tokens. */ public function testEntityReferenceTokensCardinality() { /** @var \Drupal\field\FieldStorageConfigInterface $storage */ $storage = FieldStorageConfig::load('node.test_term_reference'); $storage->setCardinality(FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED); $storage->save(); // Add a few terms. $terms = []; $terms_value = []; foreach (range(1, 3) as $i) { $terms_value[$i] = $this->randomString(); $terms[$i] = $this->createTerm($this->vocabulary, ['name' => $this->randomString(), 'term_field' => ['value' => $terms_value[$i], 'format' => $this->testFormat->id()]]); } $entity = Node::create(['title' => 'Test multivalue chained tokens', 'type' => 'article', 'test_term_reference' => [['target_id' => $terms[1]->id()], ['target_id' => $terms[2]->id()], ['target_id' => $terms[3]->id()]]]); $entity->save(); $this->assertTokens('node', ['node' => $entity], ['test_term_reference:0:entity:term_field' => Html::escape($terms[1]->term_field->value), 'test_term_reference:1:entity:term_field' => Html::escape($terms[2]->term_field->value), 'test_term_reference:2:entity:term_field' => Html::escape($terms[3]->term_field->value), 'test_term_reference:0:target_id' => $terms[1]->id(), 'test_term_reference:1:target_id' => $terms[2]->id(), 'test_term_reference:2:target_id' => $terms[3]->id(), 'test_term_reference:0:entity' => $terms[1]->label(), 'test_term_reference:1:entity' => $terms[2]->label(), 'test_term_reference:2:entity' => $terms[3]->label(), 'test_term_reference:entity:term_field' => Html::escape($terms[1]->term_field->value), 'test_term_reference:target_id' => $terms[1]->id()]); // Test some non existent tokens. $this->assertNoTokens('node', ['node' => $entity], ['test_term_reference:3:term_field', 'test_term_reference:0:does_not_exist', 'test_term_reference:1:does:not:exist', 'test_term_reference:1:2:does_not_exist']); }