Updated Drupal to 8.6. This goes with the following updates because it's possible...
[yaffs-website] / web / core / modules / field / tests / src / Functional / EntityReference / EntityReferenceAutoCreateTest.php
1 <?php
2
3 namespace Drupal\Tests\field\Functional\EntityReference;
4
5 use Drupal\Core\Field\FieldStorageDefinitionInterface;
6 use Drupal\field\Entity\FieldConfig;
7 use Drupal\Tests\BrowserTestBase;
8 use Drupal\Tests\field\Traits\EntityReferenceTestTrait;
9 use Drupal\taxonomy\Entity\Vocabulary;
10 use Drupal\node\Entity\Node;
11 use Drupal\field\Entity\FieldStorageConfig;
12
13 /**
14  * Tests creating new entity (e.g. taxonomy-term) from an autocomplete widget.
15  *
16  * @group entity_reference
17  */
18 class EntityReferenceAutoCreateTest extends BrowserTestBase {
19
20   use EntityReferenceTestTrait;
21
22   public static $modules = ['node', 'taxonomy'];
23
24   /**
25    * The name of a content type that will reference $referencedType.
26    *
27    * @var string
28    */
29   protected $referencingType;
30
31   /**
32    * The name of a content type that will be referenced by $referencingType.
33    *
34    * @var string
35    */
36   protected $referencedType;
37
38   protected function setUp() {
39     parent::setUp();
40
41     // Create "referencing" and "referenced" node types.
42     $referencing = $this->drupalCreateContentType();
43     $this->referencingType = $referencing->id();
44
45     $referenced = $this->drupalCreateContentType();
46     $this->referencedType = $referenced->id();
47
48     FieldStorageConfig::create([
49       'field_name' => 'test_field',
50       'entity_type' => 'node',
51       'translatable' => FALSE,
52       'entity_types' => [],
53       'settings' => [
54         'target_type' => 'node',
55       ],
56       'type' => 'entity_reference',
57       'cardinality' => FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED,
58     ])->save();
59
60     FieldConfig::create([
61       'label' => 'Entity reference field',
62       'field_name' => 'test_field',
63       'entity_type' => 'node',
64       'bundle' => $referencing->id(),
65       'settings' => [
66         'handler' => 'default',
67         'handler_settings' => [
68           // Reference a single vocabulary.
69           'target_bundles' => [
70             $referenced->id(),
71           ],
72           // Enable auto-create.
73           'auto_create' => TRUE,
74         ],
75       ],
76     ])->save();
77
78     entity_get_display('node', $referencing->id(), 'default')
79       ->setComponent('test_field')
80       ->save();
81     entity_get_form_display('node', $referencing->id(), 'default')
82       ->setComponent('test_field', [
83         'type' => 'entity_reference_autocomplete',
84       ])
85       ->save();
86
87     $account = $this->drupalCreateUser(['access content', "create $this->referencingType content"]);
88     $this->drupalLogin($account);
89   }
90
91   /**
92    * Tests that the autocomplete input element appears and the creation of a new
93    * entity.
94    */
95   public function testAutoCreate() {
96     $this->drupalGet('node/add/' . $this->referencingType);
97     $this->assertFieldByXPath('//input[@id="edit-test-field-0-target-id" and contains(@class, "form-autocomplete")]', NULL, 'The autocomplete input element appears.');
98
99     $new_title = $this->randomMachineName();
100
101     // Assert referenced node does not exist.
102     $base_query = \Drupal::entityQuery('node');
103     $base_query
104       ->condition('type', $this->referencedType)
105       ->condition('title', $new_title);
106
107     $query = clone $base_query;
108     $result = $query->execute();
109     $this->assertFalse($result, 'Referenced node does not exist yet.');
110
111     $edit = [
112       'title[0][value]' => $this->randomMachineName(),
113       'test_field[0][target_id]' => $new_title,
114     ];
115     $this->drupalPostForm("node/add/$this->referencingType", $edit, 'Save');
116
117     // Assert referenced node was created.
118     $query = clone $base_query;
119     $result = $query->execute();
120     $this->assertTrue($result, 'Referenced node was created.');
121     $referenced_nid = key($result);
122     $referenced_node = Node::load($referenced_nid);
123
124     // Assert the referenced node is associated with referencing node.
125     $result = \Drupal::entityQuery('node')
126       ->condition('type', $this->referencingType)
127       ->execute();
128
129     $referencing_nid = key($result);
130     $referencing_node = Node::load($referencing_nid);
131     $this->assertEqual($referenced_nid, $referencing_node->test_field->target_id, 'Newly created node is referenced from the referencing node.');
132
133     // Now try to view the node and check that the referenced node is shown.
134     $this->drupalGet('node/' . $referencing_node->id());
135     $this->assertText($referencing_node->label(), 'Referencing node label found.');
136     $this->assertText($referenced_node->label(), 'Referenced node label found.');
137   }
138
139   /**
140    * Tests if an entity reference field having multiple target bundles is
141    * storing the auto-created entity in the right destination.
142    */
143   public function testMultipleTargetBundles() {
144     /** @var \Drupal\taxonomy\Entity\Vocabulary[] $vocabularies */
145     $vocabularies = [];
146     for ($i = 0; $i < 2; $i++) {
147       $vid = mb_strtolower($this->randomMachineName());
148       $vocabularies[$i] = Vocabulary::create([
149         'name' => $this->randomMachineName(),
150         'vid' => $vid,
151       ]);
152       $vocabularies[$i]->save();
153     }
154
155     // Create a taxonomy term entity reference field that saves the auto-created
156     // taxonomy terms in the second vocabulary from the two that were configured
157     // as targets.
158     $field_name = mb_strtolower($this->randomMachineName());
159     $handler_settings = [
160       'target_bundles' => [
161         $vocabularies[0]->id() => $vocabularies[0]->id(),
162         $vocabularies[1]->id() => $vocabularies[1]->id(),
163       ],
164       'auto_create' => TRUE,
165       'auto_create_bundle' => $vocabularies[1]->id(),
166     ];
167     $this->createEntityReferenceField('node', $this->referencingType, $field_name, $this->randomString(), 'taxonomy_term', 'default', $handler_settings);
168     /** @var \Drupal\Core\Entity\Display\EntityFormDisplayInterface $fd */
169     entity_get_form_display('node', $this->referencingType, 'default')
170       ->setComponent($field_name, ['type' => 'entity_reference_autocomplete'])
171       ->save();
172
173     $term_name = $this->randomString();
174     $edit = [
175       $field_name . '[0][target_id]' => $term_name,
176       'title[0][value]' => $this->randomString(),
177     ];
178
179     $this->drupalPostForm('node/add/' . $this->referencingType, $edit, 'Save');
180     /** @var \Drupal\taxonomy\Entity\Term $term */
181     $term = taxonomy_term_load_multiple_by_name($term_name);
182     $term = reset($term);
183
184     // The new term is expected to be stored in the second vocabulary.
185     $this->assertEqual($vocabularies[1]->id(), $term->bundle());
186
187     /** @var \Drupal\field\Entity\FieldConfig $field_config */
188     $field_config = FieldConfig::loadByName('node', $this->referencingType, $field_name);
189     $handler_settings = $field_config->getSetting('handler_settings');
190
191     // Change the field setting to store the auto-created terms in the first
192     // vocabulary and test again.
193     $handler_settings['auto_create_bundle'] = $vocabularies[0]->id();
194     $field_config->setSetting('handler_settings', $handler_settings);
195     $field_config->save();
196
197     $term_name = $this->randomString();
198     $edit = [
199       $field_name . '[0][target_id]' => $term_name,
200       'title[0][value]' => $this->randomString(),
201     ];
202
203     $this->drupalPostForm('node/add/' . $this->referencingType, $edit, 'Save');
204     /** @var \Drupal\taxonomy\Entity\Term $term */
205     $term = taxonomy_term_load_multiple_by_name($term_name);
206     $term = reset($term);
207
208     // The second term is expected to be stored in the first vocabulary.
209     $this->assertEqual($vocabularies[0]->id(), $term->bundle());
210
211     // @todo Re-enable this test when WebTestBase::curlHeaderCallback() provides
212     //   a way to catch and assert user-triggered errors.
213
214     // Test the case when the field config settings are inconsistent.
215     // unset($handler_settings['auto_create_bundle']);
216     // $field_config->setSetting('handler_settings', $handler_settings);
217     // $field_config->save();
218     //
219     // $this->drupalGet('node/add/' . $this->referencingType);
220     // $error_message = sprintf(
221     //  "Create referenced entities if they don't already exist option is enabled but a specific destination bundle is not set. You should re-visit and fix the settings of the '%s' (%s) field.",
222     //  $field_config->getLabel(),
223     //  $field_config->getName()
224     // );
225     // $this->assertErrorLogged($error_message);
226   }
227
228 }