3f182c91e80b18f3ba321072111d992d5c7fbdc1
[yaffs-website] / web / core / tests / Drupal / KernelTests / Core / Entity / ValidReferenceConstraintValidatorTest.php
1 <?php
2
3 namespace Drupal\KernelTests\Core\Entity;
4
5 use Drupal\Core\Field\BaseFieldDefinition;
6 use Drupal\Core\Field\FieldStorageDefinitionInterface;
7 use Drupal\entity_test\Entity\EntityTest;
8 use Drupal\field\Entity\FieldConfig;
9 use Drupal\field\Tests\EntityReference\EntityReferenceTestTrait;
10 use Drupal\node\Entity\Node;
11 use Drupal\node\NodeInterface;
12 use Drupal\Tests\node\Traits\ContentTypeCreationTrait;
13 use Drupal\user\Entity\Role;
14 use Drupal\user\Entity\User;
15
16 /**
17  * Tests validation constraints for ValidReferenceConstraintValidator.
18  *
19  * @group Validation
20  */
21 class ValidReferenceConstraintValidatorTest extends EntityKernelTestBase {
22
23   use EntityReferenceTestTrait;
24   use ContentTypeCreationTrait;
25
26   /**
27    * The typed data manager to use.
28    *
29    * @var \Drupal\Core\TypedData\TypedDataManager
30    */
31   protected $typedData;
32
33   /**
34    * {@inheritdoc}
35    */
36   public static $modules = ['field', 'node', 'user'];
37
38   /**
39    * {@inheritdoc}
40    */
41   protected function setUp() {
42     parent::setUp();
43     $this->installSchema('user', ['users_data']);
44     $this->installSchema('node', ['node_access']);
45     $this->installConfig('node');
46     $this->typedData = $this->container->get('typed_data_manager');
47
48     $this->createContentType(['type' => 'article', 'name' => 'Article']);
49     $this->createContentType(['type' => 'page', 'name' => 'Basic page']);
50   }
51
52   /**
53    * Tests the ValidReferenceConstraintValidator.
54    */
55   public function testValidation() {
56     // Create a test entity to be referenced.
57     $entity = $this->createUser();
58     // By default entity references already have the ValidReference constraint.
59     $definition = BaseFieldDefinition::create('entity_reference')
60       ->setSettings(['target_type' => 'user']);
61
62     $typed_data = $this->typedData->create($definition, ['target_id' => $entity->id()]);
63     $violations = $typed_data->validate();
64     $this->assertFalse($violations->count(), 'Validation passed for correct value.');
65
66     // NULL is also considered a valid reference.
67     $typed_data = $this->typedData->create($definition, ['target_id' => NULL]);
68     $violations = $typed_data->validate();
69     $this->assertFalse($violations->count(), 'Validation passed for correct value.');
70
71     $typed_data = $this->typedData->create($definition, ['target_id' => $entity->id()]);
72     // Delete the referenced entity.
73     $entity->delete();
74     $violations = $typed_data->validate();
75     $this->assertTrue($violations->count(), 'Validation failed for incorrect value.');
76
77     // Make sure the information provided by a violation is correct.
78     $violation = $violations[0];
79     $this->assertEqual($violation->getMessage(), t('The referenced entity (%type: %id) does not exist.', [
80       '%type' => 'user',
81       '%id' => $entity->id(),
82     ]), 'The message for invalid value is correct.');
83     $this->assertEqual($violation->getRoot(), $typed_data, 'Violation root is correct.');
84   }
85
86   /**
87    * Tests the validation of pre-existing items in an entity reference field.
88    */
89   public function testPreExistingItemsValidation() {
90     // Create two types of users, with and without access to bypass content
91     // access.
92     /** @var \Drupal\user\RoleInterface $role_with_access */
93     $role_with_access = Role::create(['id' => 'role_with_access']);
94     $role_with_access->grantPermission('access content');
95     $role_with_access->grantPermission('bypass node access');
96     $role_with_access->save();
97
98     /** @var \Drupal\user\RoleInterface $role_without_access */
99     $role_without_access = Role::create(['id' => 'role_without_access']);
100     $role_without_access->grantPermission('access content');
101     $role_without_access->save();
102
103     $user_with_access = User::create(['roles' => ['role_with_access']]);
104     $user_without_access = User::create(['roles' => ['role_without_access']]);
105
106     // Add an entity reference field.
107     $this->createEntityReferenceField(
108       'entity_test',
109       'entity_test',
110       'field_test',
111       'Field test',
112       'node',
113       'default',
114       ['target_bundles' => ['article', 'page']],
115       FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED
116     );
117
118     // Create four test nodes.
119     $published_node = Node::create([
120       'title' => 'Test published node',
121       'type' => 'article',
122       'status' => NodeInterface::PUBLISHED,
123     ]);
124     $published_node->save();
125
126     $unpublished_node = Node::create([
127       'title' => 'Test unpublished node',
128       'type' => 'article',
129       'status' => NodeInterface::NOT_PUBLISHED,
130     ]);
131     $unpublished_node->save();
132
133     $different_bundle_node = Node::create([
134       'title' => 'Test page node',
135       'type' => 'page',
136       'status' => NodeInterface::PUBLISHED,
137     ]);
138     $different_bundle_node->save();
139
140     $deleted_node = Node::create([
141       'title' => 'Test deleted node',
142       'type' => 'article',
143       'status' => NodeInterface::PUBLISHED,
144     ]);
145     $deleted_node->save();
146
147     $referencing_entity = EntityTest::create([
148       'field_test' => [
149         ['entity' => $published_node],
150         ['entity' => $unpublished_node],
151         ['entity' => $different_bundle_node],
152         ['entity' => $deleted_node],
153       ]
154     ]);
155
156     // Check that users with access are able pass the validation for fields
157     // without pre-existing content.
158     $this->container->get('account_switcher')->switchTo($user_with_access);
159
160     $violations = $referencing_entity->field_test->validate();
161     $this->assertCount(0, $violations);
162
163     // Check that users without access are not able pass the validation for
164     // fields without pre-existing content.
165     $this->container->get('account_switcher')->switchTo($user_without_access);
166
167     $violations = $referencing_entity->field_test->validate();
168     $this->assertCount(1, $violations);
169     $this->assertEquals(t('This entity (%type: %id) cannot be referenced.', [
170       '%type' => 'node',
171       '%id' => $unpublished_node->id(),
172     ]), $violations[0]->getMessage());
173
174     // Now save the referencing entity which will create a pre-existing state
175     // for it and repeat the checks. This time, the user without access should
176     // be able to pass the validation as well because it's not changing the
177     // pre-existing state.
178     $referencing_entity->save();
179
180     $this->container->get('account_switcher')->switchTo($user_with_access);
181
182     $violations = $referencing_entity->field_test->validate();
183     $this->assertCount(0, $violations);
184
185     // Check that users without access are able pass the validation for fields
186     // with pre-existing content.
187     $this->container->get('account_switcher')->switchTo($user_without_access);
188
189     $violations = $referencing_entity->field_test->validate();
190     $this->assertCount(0, $violations);
191
192     // Re-save the referencing entity and check that the referenced entity is
193     // not affected.
194     $referencing_entity->name->value = $this->randomString();
195     $referencing_entity->save();
196     $this->assertEquals($published_node->id(), $referencing_entity->field_test[0]->target_id);
197     $this->assertEquals($unpublished_node->id(), $referencing_entity->field_test[1]->target_id);
198     $this->assertEquals($different_bundle_node->id(), $referencing_entity->field_test[2]->target_id);
199     $this->assertEquals($deleted_node->id(), $referencing_entity->field_test[3]->target_id);
200
201     $violations = $referencing_entity->field_test->validate();
202     $this->assertCount(0, $violations);
203
204     // Remove one of the referencable bundles and check that a pre-existing node
205     // of that bundle can not be referenced anymore.
206     $field = FieldConfig::loadByName('entity_test', 'entity_test', 'field_test');
207     $field->setSetting('handler_settings', ['target_bundles' => ['article']]);
208     $field->save();
209     $referencing_entity = $this->reloadEntity($referencing_entity);
210
211     $violations = $referencing_entity->field_test->validate();
212     $this->assertCount(1, $violations);
213     $this->assertEquals(t('This entity (%type: %id) cannot be referenced.', [
214       '%type' => 'node',
215       '%id' => $different_bundle_node->id(),
216     ]), $violations[0]->getMessage());
217
218     // Delete the last node and check that the pre-existing reference is not
219     // valid anymore.
220     $deleted_node->delete();
221
222     $violations = $referencing_entity->field_test->validate();
223     $this->assertCount(2, $violations);
224     $this->assertEquals(t('This entity (%type: %id) cannot be referenced.', [
225       '%type' => 'node',
226       '%id' => $different_bundle_node->id(),
227     ]), $violations[0]->getMessage());
228     $this->assertEquals(t('The referenced entity (%type: %id) does not exist.', [
229       '%type' => 'node',
230       '%id' => $deleted_node->id(),
231     ]), $violations[1]->getMessage());
232   }
233
234 }