/** * Constructs a new FieldStorageConfigListBuilder object. * * @param \Drupal\Core\Entity\EntityTypeInterface $entity_type * The entity type definition. * @param \Drupal\Core\Entity\EntityManagerInterface $entity_manager * The entity manager. * @param \Drupal\Core\Field\FieldTypePluginManagerInterface $field_type_manager * The 'field type' plugin manager. */ public function __construct(EntityTypeInterface $entity_type, EntityManagerInterface $entity_manager, FieldTypePluginManagerInterface $field_type_manager) { parent::__construct($entity_type, $entity_manager->getStorage($entity_type->id())); $this->entityManager = $entity_manager; $this->bundles = entity_get_bundles(); $this->fieldTypeManager = $field_type_manager; $this->fieldTypes = $this->fieldTypeManager->getDefinitions(); }
/** * {@inheritdoc} */ public function submitForm(array &$form, FormStateInterface $form_state) { $bundles = entity_get_bundles(); $bundle_label = $bundles[$this->fieldGroup->entity_type][$this->fieldGroup->bundle]['label']; field_group_group_delete($this->fieldGroup); drupal_set_message(t('The group %group has been deleted from the %type content type.', array('%group' => t($this->fieldGroup->label), '%type' => $bundle_label))); // Redirect. $form_state->setRedirectUrl($this->getCancelUrl()); }
/** * {@inheritdoc} */ public function buildForm(array $form, FormStateInterface $form_state) { $bundles = entity_get_bundles($this->entity->id()); if (!empty($bundles) && empty($bundles[$this->entity->id()])) { $warning_message = '<p>' . $this->formatPlural(count($bundles), '%type has 1 bundle. Please delete all %type bundles.', '%type has @count bundles. Please delete all %type bundles.', array('%type' => $this->entity->label())) . '</p>'; $form['description'] = array('#markup' => $warning_message); $form['title'] = $this->getQuestion(); return $form; } return parent::buildForm($form, $form_state); }
/** * Overrides \Drupal\views\Plugin\views\filter\InOperator::getValueOptions(). */ public function getValueOptions() { if (!isset($this->value_options)) { $types = entity_get_bundles($this->entityTypeId); $this->value_title = t('@entity types', array('@entity' => $this->entityType->getLabel())); $options = array(); foreach ($types as $type => $info) { $options[$type] = $info['label']; } asort($options); $this->value_options = $options; } return $this->value_options; }
protected function setUp() { parent::setUp(); $this->drupalCreateContentType(array('type' => 'test_bundle')); $this->drupalCreateContentType(array('type' => 'test_bundle_2')); $this->entityBundles = entity_get_bundles('node'); $this->entities['count'] = 0; foreach ($this->entityBundles as $key => $info) { for ($i = 0; $i < 5; $i++) { $entity = entity_create('node', array('label' => $this->randomMachineName(), 'uid' => 1, 'type' => $key)); $entity->save(); $this->entities[$key][$entity->id()] = $entity; $this->entities['count']++; } } }
/** * {@inheritdoc} */ public function getDerivativeDefinitions($base_plugin_definition) { // Also keep the 'entity' defined as is. $this->derivatives[''] = $base_plugin_definition; // Add definitions for each entity type and bundle. foreach ($this->entityManager->getDefinitions() as $entity_type_id => $entity_type) { $this->derivatives[$entity_type_id] = array('label' => $entity_type->getLabel(), 'constraints' => $entity_type->getConstraints()) + $base_plugin_definition; // Incorporate the bundles as entity:$entity_type:$bundle, if any. foreach (entity_get_bundles($entity_type_id) as $bundle => $bundle_info) { if ($bundle !== $entity_type_id) { $this->derivatives[$entity_type_id . ':' . $bundle] = array('label' => $bundle_info['label'], 'constraints' => $this->derivatives[$entity_type_id]['constraints']) + $base_plugin_definition; } } } return $this->derivatives; }
/** * {@inheritdoc} */ public function buildForm(array $form, FormStateInterface $form_state, FieldConfigInterface $field_config = NULL) { $this->field = $field_config; $form_state->set('field', $field_config); $bundle = $this->field->bundle; $entity_type = $this->field->entity_type; $field_storage = $this->field->getFieldStorageDefinition(); $bundles = entity_get_bundles(); $form_title = $this->t('%field settings for %bundle', array('%field' => $this->field->getLabel(), '%bundle' => $bundles[$entity_type][$bundle]['label'])); $form['#title'] = $form_title; $form['#field'] = $field_storage; // Create an arbitrary entity object (used by the 'default value' widget). $ids = (object) array('entity_type' => $this->field->entity_type, 'bundle' => $this->field->bundle, 'entity_id' => NULL); $form['#entity'] = _field_create_entity_from_ids($ids); $items = $form['#entity']->get($this->field->getName()); $item = $items->first() ?: $items->appendItem(); if (!empty($field_storage->locked)) { $form['locked'] = array('#markup' => $this->t('The field %field is locked and cannot be edited.', array('%field' => $this->field->getLabel()))); return $form; } // Create a form structure for the field values. $form['field'] = array('#tree' => TRUE); // Build the non-configurable field values. $form['field']['field_name'] = array('#type' => 'value', '#value' => $this->field->getName()); $form['field']['entity_type'] = array('#type' => 'value', '#value' => $entity_type); $form['field']['bundle'] = array('#type' => 'value', '#value' => $bundle); // Build the configurable field values. $form['field']['label'] = array('#type' => 'textfield', '#title' => $this->t('Label'), '#default_value' => $this->field->getLabel() ?: $field_storage->getName(), '#required' => TRUE, '#weight' => -20); $form['field']['description'] = array('#type' => 'textarea', '#title' => $this->t('Help text'), '#default_value' => $this->field->getDescription(), '#rows' => 5, '#description' => $this->t('Instructions to present to the user below this field on the editing form.<br />Allowed HTML tags: @tags', array('@tags' => $this->displayAllowedTags())) . '<br />' . $this->t('This field supports tokens.'), '#weight' => -10); $form['field']['required'] = array('#type' => 'checkbox', '#title' => $this->t('Required field'), '#default_value' => $this->field->isRequired(), '#weight' => -5); // Add field settings for the field type and a container for third party // settings that modules can add to via hook_form_FORM_ID_alter(). $form['field']['settings'] = $item->fieldSettingsForm($form, $form_state); $form['field']['settings']['#weight'] = 10; $form['field']['third_party_settings'] = array(); $form['field']['third_party_settings']['#weight'] = 11; // Add handling for default value. if ($element = $items->defaultValuesForm($form, $form_state)) { $element = array_merge($element, array('#type' => 'details', '#title' => $this->t('Default value'), '#open' => TRUE, '#description' => $this->t('The default value for this field, used when creating new content.'))); $form['field']['default_value'] = $element; } $form['actions'] = array('#type' => 'actions'); $form['actions']['submit'] = array('#type' => 'submit', '#value' => $this->t('Save settings'), '#button_type' => 'primary'); $form['actions']['delete'] = array('#type' => 'submit', '#value' => $this->t('Delete field'), '#submit' => array('::delete')); return $form; }
protected function setUp() { parent::setUp(FALSE); $this->drupalCreateContentType(array('type' => 'test_bundle')); $this->drupalCreateContentType(array('type' => 'test_bundle_2')); ViewTestData::createTestViews(get_class($this), array('views_test_config')); $this->entityBundles = entity_get_bundles('node'); $this->entities['count'] = 0; foreach ($this->entityBundles as $key => $info) { for ($i = 0; $i < 5; $i++) { $entity = Node::create(['title' => $this->randomString(), 'uid' => 1, 'type' => $key]); $entity->save(); $this->entities[$key][$entity->id()] = $entity; $this->entities['count']++; } } }
/** * @param \Drupal\field\Plugin\Core\Entity\Field[] $fields * * @return array */ protected function buildLegend(array $fields) { $types = array(); foreach ($fields as $field_name => $field) { foreach ($field['bundles'] as $entity_type => $bundles) { $bundle_info = entity_get_bundles($entity_type); foreach ($bundles as $bundle) { if (!isset($types[$bundle])) { $types[$bundle]['entity_type'] = $entity_type; $types[$bundle]['field_name'] = $field_name; $types[$bundle]['bundle'] = $bundle; $types[$bundle]['label'] = $bundle_info[$bundle]['label']; } } } } return $types; }
/** * {@inheritdoc} */ public function getReferenceableEntities($match = NULL, $match_operator = 'CONTAINS', $limit = 0) { if ($match || $limit) { return parent::getReferenceableEntities($match, $match_operator, $limit); } $options = array(); $bundles = entity_get_bundles('taxonomy_term'); $bundle_names = !empty($this->instance['settings']['handler_settings']['target_bundles']) ? $this->instance['settings']['handler_settings']['target_bundles'] : array_keys($bundles); foreach ($bundle_names as $bundle) { if ($vocabulary = entity_load('taxonomy_vocabulary', $bundle)) { if ($terms = taxonomy_get_tree($vocabulary->id(), 0, NULL, TRUE)) { foreach ($terms as $term) { $options[$vocabulary->id()][$term->id()] = str_repeat('-', $term->depth) . String::checkPlain($term->getName()); } } } } return $options; }
/** * {@inheritdoc} */ public function submitForm(array &$form, FormStateInterface $form_state) { $field_storage = $this->entity->getFieldStorageDefinition(); $bundles = entity_get_bundles(); $bundle_label = $bundles[$this->entity->entity_type][$this->entity->bundle]['label']; if ($field_storage && !$field_storage->locked) { $this->entity->delete(); drupal_set_message($this->t('The field %field has been deleted from the %type content type.', array('%field' => $this->entity->label(), '%type' => $bundle_label))); } else { drupal_set_message($this->t('There was a problem removing the %field from the %type content type.', array('%field' => $this->entity->label(), '%type' => $bundle_label)), 'error'); } $form_state->setRedirectUrl($this->getCancelUrl()); // Fields are purged on cron. However field module prevents disabling modules // when field types they provided are used in a field until it is fully // purged. In the case that a field has minimal or no content, a single call // to field_purge_batch() will remove it from the system. Call this with a // low batch limit to avoid administrators having to wait for cron runs when // removing fields that meet this criteria. field_purge_batch(10); }
/** * {@inheritdoc} */ public function buildForm(array $form, FormStateInterface $form_state, FieldInstanceConfigInterface $field_instance_config = NULL) { $this->instance = $form_state['instance'] = $field_instance_config; $bundle = $this->instance->bundle; $entity_type = $this->instance->entity_type; $field_storage = $this->instance->getFieldStorageDefinition(); $bundles = entity_get_bundles(); $form_title = $this->t('%instance settings for %bundle', array('%instance' => $this->instance->getLabel(), '%bundle' => $bundles[$entity_type][$bundle]['label'])); $form['#title'] = $form_title; $form['#field'] = $field_storage; // Create an arbitrary entity object (used by the 'default value' widget). $ids = (object) array('entity_type' => $this->instance->entity_type, 'bundle' => $this->instance->bundle, 'entity_id' => NULL); $form['#entity'] = _field_create_entity_from_ids($ids); $items = $form['#entity']->get($this->instance->getName()); if (!empty($field_storage->locked)) { $form['locked'] = array('#markup' => $this->t('The field %field is locked and cannot be edited.', array('%field' => $this->instance->getLabel()))); return $form; } // Create a form structure for the instance values. $form['instance'] = array('#tree' => TRUE); // Build the non-configurable instance values. $form['instance']['field_name'] = array('#type' => 'value', '#value' => $this->instance->getName()); $form['instance']['entity_type'] = array('#type' => 'value', '#value' => $entity_type); $form['instance']['bundle'] = array('#type' => 'value', '#value' => $bundle); // Build the configurable instance values. $form['instance']['label'] = array('#type' => 'textfield', '#title' => $this->t('Label'), '#default_value' => $this->instance->getLabel() ?: $field_storage->getName(), '#required' => TRUE, '#weight' => -20); $form['instance']['description'] = array('#type' => 'textarea', '#title' => $this->t('Help text'), '#default_value' => $this->instance->getDescription(), '#rows' => 5, '#description' => $this->t('Instructions to present to the user below this field on the editing form.<br />Allowed HTML tags: @tags', array('@tags' => _field_filter_xss_display_allowed_tags())) . '<br />' . $this->t('This field supports tokens.'), '#weight' => -10); $form['instance']['required'] = array('#type' => 'checkbox', '#title' => $this->t('Required field'), '#default_value' => $this->instance->isRequired(), '#weight' => -5); // Add instance settings for the field type. $form['instance']['settings'] = $items[0]->instanceSettingsForm($form, $form_state); $form['instance']['settings']['#weight'] = 10; // Add handling for default value. if ($element = $items->defaultValuesForm($form, $form_state)) { $element += array('#type' => 'details', '#title' => $this->t('Default value'), '#open' => TRUE, '#description' => $this->t('The default value for this field, used when creating new content.')); $form['instance']['default_value'] = $element; } $form['actions'] = array('#type' => 'actions'); $form['actions']['submit'] = array('#type' => 'submit', '#value' => $this->t('Save settings')); $form['actions']['delete'] = array('#type' => 'submit', '#value' => $this->t('Delete field'), '#submit' => array(array($this, 'delete'))); return $form; }
/** * Tests the Entity Reference Admin UI. */ public function testFieldAdminHandler() { $bundle_path = 'admin/structure/types/manage/' . $this->type; // First step: 'Add new field' on the 'Manage fields' page. $this->drupalPostForm($bundle_path . '/fields', array('fields[_add_new_field][label]' => 'Test label', 'fields[_add_new_field][field_name]' => 'test', 'fields[_add_new_field][type]' => 'entity_reference'), t('Save')); // Node should be selected by default. $this->assertFieldByName('field[settings][target_type]', 'node'); // Check that all entity types can be referenced. $this->assertFieldSelectOptions('field[settings][target_type]', array_keys(\Drupal::entityManager()->getDefinitions())); // Second step: 'Instance settings' form. $this->drupalPostForm(NULL, array(), t('Save field settings')); // The base handler should be selected by default. $this->assertFieldByName('instance[settings][handler]', 'default'); // The base handler settings should be displayed. $entity_type_id = 'node'; $bundles = entity_get_bundles($entity_type_id); foreach ($bundles as $bundle_name => $bundle_info) { $this->assertFieldByName('instance[settings][handler_settings][target_bundles][' . $bundle_name . ']'); } reset($bundles); // Test the sort settings. // Option 0: no sort. $this->assertFieldByName('instance[settings][handler_settings][sort][field]', '_none'); $this->assertNoFieldByName('instance[settings][handler_settings][sort][direction]'); // Option 1: sort by field. $this->drupalPostAjaxForm(NULL, array('instance[settings][handler_settings][sort][field]' => 'nid'), 'instance[settings][handler_settings][sort][field]'); $this->assertFieldByName('instance[settings][handler_settings][sort][direction]', 'ASC'); // Test that a non-translatable base field is a sort option. $this->assertFieldByXPath("//select[@name='instance[settings][handler_settings][sort][field]']/option[@value='nid']"); // Test that a translatable base field is a sort option. $this->assertFieldByXPath("//select[@name='instance[settings][handler_settings][sort][field]']/option[@value='title']"); // Test that a configurable field is a sort option. $this->assertFieldByXPath("//select[@name='instance[settings][handler_settings][sort][field]']/option[@value='body.value']"); // Set back to no sort. $this->drupalPostAjaxForm(NULL, array('instance[settings][handler_settings][sort][field]' => '_none'), 'instance[settings][handler_settings][sort][field]'); $this->assertNoFieldByName('instance[settings][handler_settings][sort][direction]'); // Third step: confirm. $this->drupalPostForm(NULL, array('instance[settings][handler_settings][target_bundles][' . key($bundles) . ']' => key($bundles)), t('Save settings')); // Check that the field appears in the overview form. $this->assertFieldByXPath('//table[@id="field-overview"]//tr[@id="field-test"]/td[1]', 'Test label', 'Field was created and appears in the overview page.'); }
/** * Writes the cache of type links. */ protected function writeCache() { $data = array(); // Type URIs correspond to bundles. Iterate through the bundles to get the // URI and data for them. $entity_types = \Drupal::entityManager()->getDefinitions(); foreach (entity_get_bundles() as $entity_type_id => $bundles) { // Only content entities are supported currently. // @todo Consider supporting config entities. if ($entity_types[$entity_type_id]->isSubclassOf('\\Drupal\\Core\\Config\\Entity\\ConfigEntityInterface')) { continue; } foreach ($bundles as $bundle => $bundle_info) { // Get a type URI for the bundle. $bundle_uri = $this->getTypeUri($entity_type_id, $bundle); $data[$bundle_uri] = array('entity_type' => $entity_type_id, 'bundle' => $bundle); } } // These URIs only change when entity info changes, so cache it permanently // and only clear it when entity_info is cleared. $this->cache->set('rest:links:types', $data, Cache::PERMANENT, array('entity_types')); }
/** * {@inheritdoc} */ public function elementValidate($element, &$form_state, $form) { $value = array(); // If a value was entered into the autocomplete. $handler = \Drupal::service('plugin.manager.entity_reference.selection')->getSelectionHandler($this->fieldDefinition); $bundles = entity_get_bundles($this->getFieldSetting('target_type')); $auto_create = $this->getSelectionHandlerSetting('auto_create'); if (!empty($element['#value'])) { $value = array(); foreach (Tags::explode($element['#value']) as $input) { $match = FALSE; // Take "label (entity id)', match the ID from parenthesis when it's a // number. if (preg_match("/.+\\((\\d+)\\)/", $input, $matches)) { $match = $matches[1]; } elseif (preg_match("/.+\\(([\\w.]+)\\)/", $input, $matches)) { $match = $matches[1]; } else { // Try to get a match from the input string when the user didn't use // the autocomplete but filled in a value manually. $match = $handler->validateAutocompleteInput($input, $element, $form_state, $form, !$auto_create); } if ($match) { $value[] = array('target_id' => $match); } elseif ($auto_create && (count($this->getSelectionHandlerSetting('target_bundles')) == 1 || count($bundles) == 1)) { // Auto-create item. See // \Drupal\Core\Field\Plugin\Field\FieldType\EntityReferenceItem::presave(). $value[] = array('target_id' => NULL, 'entity' => $this->createNewEntity($input, $element['#autocreate_uid'])); } } } // Change the element['#parents'], so in form_set_value() we // populate the correct key. array_pop($element['#parents']); form_set_value($element, $value, $form_state); }
/** * Provides a list of bundle options for use in select lists. * * @return array * A keyed array of bundle => label. */ protected function bundleOptions() { $options = array(); foreach (entity_get_bundles($this->entityType()) as $bundle => $info) { if (!empty($info['label'])) { $options[$bundle] = $info['label']; } else { $options[$bundle] = $bundle; } } return $options; }
public function fieldInfoPage() { $field_info = Field::fieldInfo(); $info = $field_info->getFields(); $output = kprint_r($info, TRUE, t('Fields')); $info = $field_info->getInstances(); $output .= kprint_r($info, TRUE, t('Instances')); $info = entity_get_bundles(); $output .= kprint_r($info, TRUE, t('Bundles')); $info = \Drupal::service('plugin.manager.field.field_type')->getConfigurableDefinitions(); $output .= kprint_r($info, TRUE, t('Field types')); $info = \Drupal::service('plugin.manager.field.formatter')->getDefinitions(); $output .= kprint_r($info, TRUE, t('Formatter types')); //$info = field_info_storage_types(); //$output .= kprint_r($info, TRUE, t('Storage types')); $info = \Drupal::service('plugin.manager.field.widget')->getDefinitions(); $output .= kprint_r($info, TRUE, t('Widget types')); return $output; }
/** * Builds the form structure for selecting the view's filters. * * By default, this adds "of type" and "tagged with" filters (when they are * available). */ protected function buildFilters(&$form, FormStateInterface $form_state) { module_load_include('inc', 'views_ui', 'admin'); $bundles = entity_get_bundles($this->entityTypeId); // If the current base table support bundles and has more than one (like user). if (!empty($bundles) && $this->entityType && $this->entityType->hasKey('bundle')) { // Get all bundles and their human readable names. $options = array('all' => $this->t('All')); foreach ($bundles as $type => $bundle) { $options[$type] = $bundle['label']; } $form['displays']['show']['type'] = array('#type' => 'select', '#title' => $this->t('of type'), '#options' => $options); $selected_bundle = static::getSelected($form_state, array('show', 'type'), 'all', $form['displays']['show']['type']); $form['displays']['show']['type']['#default_value'] = $selected_bundle; // Changing this dropdown updates the entire content of $form['displays'] // via AJAX, since each bundle might have entirely different fields // attached to it, etc. views_ui_add_ajax_trigger($form['displays']['show'], 'type', array('displays')); } }
/** * Tests the Entity Reference Admin UI. */ public function testFieldAdminHandler() { $bundle_path = 'admin/structure/types/manage/' . $this->type; // First step: 'Add new field' on the 'Manage fields' page. $this->drupalGet($bundle_path . '/fields/add-field'); // Check if the commonly referenced entity types appear in the list. $this->assertOption('edit-new-storage-type', 'field_ui:entity_reference:node'); $this->assertOption('edit-new-storage-type', 'field_ui:entity_reference:user'); $this->drupalPostForm(NULL, array('label' => 'Test label', 'field_name' => 'test', 'new_storage_type' => 'entity_reference'), t('Save and continue')); // Node should be selected by default. $this->assertFieldByName('settings[target_type]', 'node'); // Check that all entity types can be referenced. $this->assertFieldSelectOptions('settings[target_type]', array_keys(\Drupal::entityManager()->getDefinitions())); // Second step: 'Field settings' form. $this->drupalPostForm(NULL, array(), t('Save field settings')); // The base handler should be selected by default. $this->assertFieldByName('settings[handler]', 'default:node'); // The base handler settings should be displayed. $entity_type_id = 'node'; $bundles = entity_get_bundles($entity_type_id); foreach ($bundles as $bundle_name => $bundle_info) { $this->assertFieldByName('settings[handler_settings][target_bundles][' . $bundle_name . ']'); } reset($bundles); // Test the sort settings. // Option 0: no sort. $this->assertFieldByName('settings[handler_settings][sort][field]', '_none'); $this->assertNoFieldByName('settings[handler_settings][sort][direction]'); // Option 1: sort by field. $this->drupalPostAjaxForm(NULL, array('settings[handler_settings][sort][field]' => 'nid'), 'settings[handler_settings][sort][field]'); $this->assertFieldByName('settings[handler_settings][sort][direction]', 'ASC'); // Test that a non-translatable base field is a sort option. $this->assertFieldByXPath("//select[@name='settings[handler_settings][sort][field]']/option[@value='nid']"); // Test that a translatable base field is a sort option. $this->assertFieldByXPath("//select[@name='settings[handler_settings][sort][field]']/option[@value='title']"); // Test that a configurable field is a sort option. $this->assertFieldByXPath("//select[@name='settings[handler_settings][sort][field]']/option[@value='body.value']"); // Set back to no sort. $this->drupalPostAjaxForm(NULL, array('settings[handler_settings][sort][field]' => '_none'), 'settings[handler_settings][sort][field]'); $this->assertNoFieldByName('settings[handler_settings][sort][direction]'); // Third step: confirm. $this->drupalPostForm(NULL, array('required' => '1', 'settings[handler_settings][target_bundles][' . key($bundles) . ']' => key($bundles)), t('Save settings')); // Check that the field appears in the overview form. $this->assertFieldByXPath('//table[@id="field-overview"]//tr[@id="field-test"]/td[1]', 'Test label', 'Field was created and appears in the overview page.'); // Check that the field settings form can be submitted again, even when the // field is required. // The first 'Edit' link is for the Body field. $this->clickLink(t('Edit'), 1); $this->drupalPostForm(NULL, array(), t('Save settings')); // Switch the target type to 'taxonomy_term' and check that the settings // specific to its selection handler are displayed. $field_name = 'node.' . $this->type . '.field_test'; $edit = array('settings[target_type]' => 'taxonomy_term'); $this->drupalPostForm($bundle_path . '/fields/' . $field_name . '/storage', $edit, t('Save field settings')); $this->drupalGet($bundle_path . '/fields/' . $field_name); $this->assertFieldByName('settings[handler_settings][auto_create]'); // Switch the target type to 'user' and check that the settings specific to // its selection handler are displayed. $field_name = 'node.' . $this->type . '.field_test'; $edit = array('settings[target_type]' => 'user'); $this->drupalPostForm($bundle_path . '/fields/' . $field_name . '/storage', $edit, t('Save field settings')); $this->drupalGet($bundle_path . '/fields/' . $field_name); $this->assertFieldByName('settings[handler_settings][filter][type]', '_none'); // Switch the target type to 'node'. $field_name = 'node.' . $this->type . '.field_test'; $edit = array('settings[target_type]' => 'node'); $this->drupalPostForm($bundle_path . '/fields/' . $field_name . '/storage', $edit, t('Save field settings')); // Try to select the views handler. $edit = array('settings[handler]' => 'views'); $this->drupalPostAjaxForm($bundle_path . '/fields/' . $field_name, $edit, 'settings[handler]'); $this->assertRaw(t('No eligible views were found. <a href=":create">Create a view</a> with an <em>Entity Reference</em> display, or add such a display to an <a href=":existing">existing view</a>.', array(':create' => \Drupal::url('views_ui.add'), ':existing' => \Drupal::url('entity.view.collection')))); $this->drupalPostForm(NULL, $edit, t('Save settings')); // If no eligible view is available we should see a message. $this->assertText('The views entity selection mode requires a view.'); // Enable the entity_reference_test module which creates an eligible view. $this->container->get('module_installer')->install(array('entity_reference_test')); $this->resetAll(); $this->drupalGet($bundle_path . '/fields/' . $field_name); $this->drupalPostAjaxForm($bundle_path . '/fields/' . $field_name, $edit, 'settings[handler]'); $edit = array('settings[handler_settings][view][view_and_display]' => 'test_entity_reference:entity_reference_1'); $this->drupalPostForm(NULL, $edit, t('Save settings')); $this->assertResponse(200); // Switch the target type to 'entity_test'. $edit = array('settings[target_type]' => 'entity_test'); $this->drupalPostForm($bundle_path . '/fields/' . $field_name . '/storage', $edit, t('Save field settings')); $this->drupalGet($bundle_path . '/fields/' . $field_name); $edit = array('settings[handler]' => 'views'); $this->drupalPostAjaxForm($bundle_path . '/fields/' . $field_name, $edit, 'settings[handler]'); $edit = array('required' => FALSE, 'settings[handler_settings][view][view_and_display]' => 'test_entity_reference_entity_test:entity_reference_1'); $this->drupalPostForm(NULL, $edit, t('Save settings')); $this->assertResponse(200); // Create a new view and display it as a entity reference. $edit = array('id' => 'node_test_view', 'label' => 'Node Test View', 'show[wizard_key]' => 'node', 'page[create]' => 1, 'page[title]' => 'Test Node View', 'page[path]' => 'test/node/view', 'page[style][style_plugin]' => 'default', 'page[style][row_plugin]' => 'fields'); $this->drupalPostForm('admin/structure/views/add', $edit, t('Save and edit')); $this->drupalPostForm(NULL, array(), t('Duplicate as Entity Reference')); $this->clickLink(t('Settings')); $edit = array('style_options[search_fields][title]' => 'title'); $this->drupalPostForm(NULL, $edit, t('Apply')); $this->drupalPostForm('admin/structure/views/view/node_test_view/edit/entity_reference_1', array(), t('Save')); $this->clickLink(t('Settings')); // Create a test entity reference field. $field_name = 'test_entity_ref_field'; $edit = array('new_storage_type' => 'field_ui:entity_reference:node', 'label' => 'Test Entity Reference Field', 'field_name' => $field_name); $this->drupalPostForm($bundle_path . '/fields/add-field', $edit, t('Save and continue')); $this->drupalPostForm(NULL, array(), t('Save field settings')); // Add the view to the test field. $edit = array('settings[handler]' => 'views'); $this->drupalPostAjaxForm(NULL, $edit, 'settings[handler]'); $edit = array('required' => FALSE, 'settings[handler_settings][view][view_and_display]' => 'node_test_view:entity_reference_1'); $this->drupalPostForm(NULL, $edit, t('Save settings')); // Create nodes. $node1 = Node::create(['type' => $this->type, 'title' => 'Foo Node']); $node1->save(); $node2 = Node::create(['type' => $this->type, 'title' => 'Foo Node']); $node2->save(); // Try to add a new node and fill the entity reference field. $this->drupalGet('node/add/' . $this->type); $result = $this->xpath('//input[@name="field_test_entity_ref_field[0][target_id]" and contains(@data-autocomplete-path, "/entity_reference_autocomplete/node/views/")]'); $target_url = $this->getAbsoluteUrl($result[0]['data-autocomplete-path']); $this->drupalGet($target_url, array('query' => array('q' => 'Foo'))); $this->assertRaw($node1->getTitle() . ' (' . $node1->id() . ')'); $this->assertRaw($node2->getTitle() . ' (' . $node2->id() . ')'); $edit = array('title[0][value]' => 'Example', 'field_test_entity_ref_field[0][target_id]' => 'Test'); $this->drupalPostForm('node/add/' . $this->type, $edit, t('Save')); // Assert that entity reference autocomplete field is validated. $this->assertText(t('There are no entities matching "@entity"', ['@entity' => 'Test'])); $edit = array('title[0][value]' => 'Test', 'field_test_entity_ref_field[0][target_id]' => $node1->getTitle()); $this->drupalPostForm('node/add/' . $this->type, $edit, t('Save')); // Assert the results multiple times to avoid sorting problem of nodes with // the same title. $this->assertText(t('Multiple entities match this reference;')); $this->assertText(t("@node1", ['@node1' => $node1->getTitle() . ' (' . $node1->id() . ')'])); $this->assertText(t("@node2", ['@node2' => $node2->getTitle() . ' (' . $node2->id() . ')'])); $edit = array('title[0][value]' => 'Test', 'field_test_entity_ref_field[0][target_id]' => $node1->getTitle() . '(' . $node1->id() . ')'); $this->drupalPostForm('node/add/' . $this->type, $edit, t('Save')); $this->assertLink($node1->getTitle()); // Tests adding default values to autocomplete widgets. Vocabulary::create(array('vid' => 'tags', 'name' => 'tags'))->save(); $taxonomy_term_field_name = $this->createEntityReferenceField('taxonomy_term', 'tags'); $field_path = 'node.' . $this->type . '.field_' . $taxonomy_term_field_name; $this->drupalGet($bundle_path . '/fields/' . $field_path . '/storage'); $edit = ['cardinality' => -1]; $this->drupalPostForm(NULL, $edit, t('Save field settings')); $this->drupalGet($bundle_path . '/fields/' . $field_path); $term_name = $this->randomString(); $edit = ['settings[handler_settings][auto_create]' => 1]; $this->drupalPostForm(NULL, $edit, t('Save settings')); $this->drupalGet($bundle_path . '/fields/' . $field_path); $edit = ['default_value_input[field_' . $taxonomy_term_field_name . '][0][target_id]' => $term_name]; $this->drupalPostForm(NULL, $edit, t('Save settings')); // The term should now exist. $term = taxonomy_term_load_multiple_by_name($term_name, 'tags')[1]; $this->assertIdentical(1, count($term), 'Taxonomy term was auto created when set as field default.'); }
/** * Returns the name of the bundle which will be used for autocreated entities. * * @return string * The bundle name. */ protected function getAutocreateBundle() { $bundle = NULL; if ($this->getSelectionHandlerSetting('auto_create')) { // If the 'target_bundles' setting is restricted to a single choice, we // can use that. if (($target_bundles = $this->getSelectionHandlerSetting('target_bundles')) && count($target_bundles) == 1) { $bundle = reset($target_bundles); } else { // @todo Expose a proper UI for choosing the bundle for autocreated // entities in https://www.drupal.org/node/2412569. $bundles = entity_get_bundles($this->getFieldSetting('target_type')); $bundle = key($bundles); } } return $bundle; }
/** * Tests the Entity Reference Admin UI. */ public function testFieldAdminHandler() { $bundle_path = 'admin/structure/types/manage/' . $this->type; // First step: 'Add new field' on the 'Manage fields' page. $this->drupalGet($bundle_path . '/fields/add-field'); // Check if the commonly referenced entity types appear in the list. $this->assertOption('edit-new-storage-type', 'field_ui:entity_reference:node'); $this->assertOption('edit-new-storage-type', 'field_ui:entity_reference:user'); $this->drupalPostForm(NULL, array('label' => 'Test label', 'field_name' => 'test', 'new_storage_type' => 'entity_reference'), t('Save and continue')); // Node should be selected by default. $this->assertFieldByName('settings[target_type]', 'node'); // Check that all entity types can be referenced. $this->assertFieldSelectOptions('settings[target_type]', array_keys(\Drupal::entityManager()->getDefinitions())); // Second step: 'Field settings' form. $this->drupalPostForm(NULL, array(), t('Save field settings')); // The base handler should be selected by default. $this->assertFieldByName('settings[handler]', 'default:node'); // The base handler settings should be displayed. $entity_type_id = 'node'; $bundles = entity_get_bundles($entity_type_id); foreach ($bundles as $bundle_name => $bundle_info) { $this->assertFieldByName('settings[handler_settings][target_bundles][' . $bundle_name . ']'); } reset($bundles); // Test the sort settings. // Option 0: no sort. $this->assertFieldByName('settings[handler_settings][sort][field]', '_none'); $this->assertNoFieldByName('settings[handler_settings][sort][direction]'); // Option 1: sort by field. $this->drupalPostAjaxForm(NULL, array('settings[handler_settings][sort][field]' => 'nid'), 'settings[handler_settings][sort][field]'); $this->assertFieldByName('settings[handler_settings][sort][direction]', 'ASC'); // Test that a non-translatable base field is a sort option. $this->assertFieldByXPath("//select[@name='settings[handler_settings][sort][field]']/option[@value='nid']"); // Test that a translatable base field is a sort option. $this->assertFieldByXPath("//select[@name='settings[handler_settings][sort][field]']/option[@value='title']"); // Test that a configurable field is a sort option. $this->assertFieldByXPath("//select[@name='settings[handler_settings][sort][field]']/option[@value='body.value']"); // Set back to no sort. $this->drupalPostAjaxForm(NULL, array('settings[handler_settings][sort][field]' => '_none'), 'settings[handler_settings][sort][field]'); $this->assertNoFieldByName('settings[handler_settings][sort][direction]'); // Third step: confirm. $this->drupalPostForm(NULL, array('required' => '1', 'settings[handler_settings][target_bundles][' . key($bundles) . ']' => key($bundles)), t('Save settings')); // Check that the field appears in the overview form. $this->assertFieldByXPath('//table[@id="field-overview"]//tr[@id="field-test"]/td[1]', 'Test label', 'Field was created and appears in the overview page.'); // Check that the field settings form can be submitted again, even when the // field is required. // The first 'Edit' link is for the Body field. $this->clickLink(t('Edit'), 1); $this->drupalPostForm(NULL, array(), t('Save settings')); // Switch the target type to 'taxonomy_term' and check that the settings // specific to its selection handler are displayed. $field_name = 'node.' . $this->type . '.field_test'; $edit = array('settings[target_type]' => 'taxonomy_term'); $this->drupalPostForm($bundle_path . '/fields/' . $field_name . '/storage', $edit, t('Save field settings')); $this->drupalGet($bundle_path . '/fields/' . $field_name); $this->assertFieldByName('settings[handler_settings][auto_create]'); // Switch the target type to 'user' and check that the settings specific to // its selection handler are displayed. $field_name = 'node.' . $this->type . '.field_test'; $edit = array('settings[target_type]' => 'user'); $this->drupalPostForm($bundle_path . '/fields/' . $field_name . '/storage', $edit, t('Save field settings')); $this->drupalGet($bundle_path . '/fields/' . $field_name); $this->assertFieldByName('settings[handler_settings][filter][type]', '_none'); // Switch the target type to 'node'. $field_name = 'node.' . $this->type . '.field_test'; $edit = array('settings[target_type]' => 'node'); $this->drupalPostForm($bundle_path . '/fields/' . $field_name . '/storage', $edit, t('Save field settings')); // Try to select the views handler. $edit = array('settings[handler]' => 'views'); $this->drupalPostAjaxForm($bundle_path . '/fields/' . $field_name, $edit, 'settings[handler]'); $this->assertRaw(t('No eligible views were found. <a href="@create">Create a view</a> with an <em>Entity Reference</em> display, or add such a display to an <a href="@existing">existing view</a>.', array('@create' => \Drupal::url('views_ui.add'), '@existing' => \Drupal::url('entity.view.collection')))); $this->drupalPostForm(NULL, $edit, t('Save settings')); // If no eligible view is available we should see a message. $this->assertText('The views entity selection mode requires a view.'); // Enable the entity_reference_test module which creates an eligible view. $this->container->get('module_installer')->install(array('entity_reference_test')); $this->resetAll(); $this->drupalGet($bundle_path . '/fields/' . $field_name); $this->drupalPostAjaxForm($bundle_path . '/fields/' . $field_name, $edit, 'settings[handler]'); $edit = array('settings[handler_settings][view][view_and_display]' => 'test_entity_reference:entity_reference_1'); $this->drupalPostForm(NULL, $edit, t('Save settings')); $this->assertResponse(200); // Switch the target type to 'entity_test'. $edit = array('settings[target_type]' => 'entity_test'); $this->drupalPostForm($bundle_path . '/fields/' . $field_name . '/storage', $edit, t('Save field settings')); $this->drupalGet($bundle_path . '/fields/' . $field_name); $edit = array('settings[handler]' => 'views'); $this->drupalPostAjaxForm($bundle_path . '/fields/' . $field_name, $edit, 'settings[handler]'); $edit = array('settings[handler_settings][view][view_and_display]' => 'test_entity_reference_entity_test:entity_reference_1'); $this->drupalPostForm(NULL, $edit, t('Save settings')); $this->assertResponse(200); }
/** * Tests that machine name changes are properly reflected. */ function testTaxonomyVocabularyChangeMachineName() { // Add a field to the vocabulary. entity_create('field_storage_config', array('field_name' => 'field_test', 'entity_type' => 'taxonomy_term', 'type' => 'test_field'))->save(); entity_create('field_config', array('field_name' => 'field_test', 'entity_type' => 'taxonomy_term', 'bundle' => $this->vocabulary->id()))->save(); // Change the machine name. $old_name = $this->vocabulary->id(); $new_name = Unicode::strtolower($this->randomMachineName()); $this->vocabulary->set('vid', $new_name); $this->vocabulary->save(); // Check that entity bundles are properly updated. $info = entity_get_bundles('taxonomy_term'); $this->assertFalse(isset($info[$old_name]), 'The old bundle name does not appear in entity_get_bundles().'); $this->assertTrue(isset($info[$new_name]), 'The new bundle name appears in entity_get_bundles().'); // Check that the field is still attached to the vocabulary. $this->assertTrue(FieldConfig::loadByName('taxonomy_term', $new_name, 'field_test'), 'The bundle name was updated correctly.'); }
/** * Overrides Drupal\views\Plugin\views\wizard\WizardPluginBase::buildFilters(). * * Add some options for filter by taxonomy terms. */ protected function buildFilters(&$form, FormStateInterface $form_state) { parent::buildFilters($form, $form_state); $selected_bundle = static::getSelected($form_state, array('show', 'type'), 'all', $form['displays']['show']['type']); // Add the "tagged with" filter to the view. // We construct this filter using taxonomy_index.tid (which limits the // filtering to a specific vocabulary) rather than // taxonomy_term_field_data.name (which matches terms in any vocabulary). // This is because it is a more commonly-used filter that works better with // the autocomplete UI, and also to avoid confusion with other vocabularies // on the site that may have terms with the same name but are not used for // free tagging. // The downside is that if there *is* more than one vocabulary on the site // that is used for free tagging, the wizard will only be able to make the // "tagged with" filter apply to one of them (see below for the method it // uses to choose). // Find all "tag-like" taxonomy fields associated with the view's // entities. If a particular entity type (i.e., bundle) has been // selected above, then we only search for taxonomy fields associated // with that bundle. Otherwise, we use all bundles. $bundles = array_keys(entity_get_bundles($this->entityTypeId)); // Double check that this is a real bundle before using it (since above // we added a dummy option 'all' to the bundle list on the form). if (isset($selected_bundle) && in_array($selected_bundle, $bundles)) { $bundles = array($selected_bundle); } $tag_fields = array(); foreach ($bundles as $bundle) { $display = entity_get_form_display($this->entityTypeId, $bundle, 'default'); $taxonomy_fields = array_filter(\Drupal::entityManager()->getFieldDefinitions($this->entityTypeId, $bundle), function ($field_definition) { return $field_definition->getType() == 'entity_reference' && $field_definition->getSetting('target_type') == 'taxonomy_term'; }); foreach ($taxonomy_fields as $field_name => $field) { $widget = $display->getComponent($field_name); // We define "tag-like" taxonomy fields as ones that use the // "Autocomplete (Tags style)" widget. if ($widget['type'] == 'entity_reference_autocomplete_tags') { $tag_fields[$field_name] = $field; } } } if (!empty($tag_fields)) { // If there is more than one "tag-like" taxonomy field available to // the view, we can only make our filter apply to one of them (as // described above). We choose 'field_tags' if it is available, since // that is created by the Standard install profile in core and also // commonly used by contrib modules; thus, it is most likely to be // associated with the "main" free-tagging vocabulary on the site. if (array_key_exists('field_tags', $tag_fields)) { $tag_field_name = 'field_tags'; } else { $tag_field_name = key($tag_fields); } // Add the autocomplete textfield to the wizard. $target_bundles = $tag_fields[$tag_field_name]->getSetting('handler_settings')['target_bundles']; $form['displays']['show']['tagged_with'] = array('#type' => 'entity_autocomplete', '#title' => $this->t('tagged with'), '#target_type' => 'taxonomy_term', '#selection_settings' => ['target_bundles' => $target_bundles], '#tags' => TRUE, '#size' => 30, '#maxlength' => 1024); } }
/** * {@inheritdoc} */ public function getType(JobItemInterface $job_item) { if ($entity = entity_load($job_item->getItemType(), $job_item->getItemId())) { $bundles = entity_get_bundles($job_item->getItemType()); $entity_type = $entity->getEntityType(); $bundle = $entity->bundle(); // Display entity type and label if we have one and the bundle isn't // the same as the entity type. if (isset($bundles[$bundle]) && $bundle != $job_item->getItemType()) { return t('@type (@bundle)', array('@type' => $entity_type->getLabel(), '@bundle' => $bundles[$bundle]['label'])); } // Otherwise just display the entity type label. return $entity_type->getLabel(); } }
/** * Tests the Entity Reference Admin UI. */ public function testFieldAdminHandler() { $bundle_path = 'admin/structure/types/manage/' . $this->type; // First step: 'Add new field' on the 'Manage fields' page. $this->drupalGet($bundle_path . '/fields/add-field'); // Check if the commonly referenced entity types appear in the list. $this->assertOption('edit-new-storage-type', 'field_ui:entity_reference:node'); $this->assertOption('edit-new-storage-type', 'field_ui:entity_reference:user'); $this->drupalPostForm(NULL, array('label' => 'Test label', 'field_name' => 'test', 'new_storage_type' => 'entity_reference'), t('Save and continue')); // Node should be selected by default. $this->assertFieldByName('field_storage[settings][target_type]', 'node'); // Check that all entity types can be referenced. $this->assertFieldSelectOptions('field_storage[settings][target_type]', array_keys(\Drupal::entityManager()->getDefinitions())); // Second step: 'Field settings' form. $this->drupalPostForm(NULL, array(), t('Save field settings')); // The base handler should be selected by default. $this->assertFieldByName('field[settings][handler]', 'default:node'); // The base handler settings should be displayed. $entity_type_id = 'node'; $bundles = entity_get_bundles($entity_type_id); foreach ($bundles as $bundle_name => $bundle_info) { $this->assertFieldByName('field[settings][handler_settings][target_bundles][' . $bundle_name . ']'); } reset($bundles); // Test the sort settings. // Option 0: no sort. $this->assertFieldByName('field[settings][handler_settings][sort][field]', '_none'); $this->assertNoFieldByName('field[settings][handler_settings][sort][direction]'); // Option 1: sort by field. $this->drupalPostAjaxForm(NULL, array('field[settings][handler_settings][sort][field]' => 'nid'), 'field[settings][handler_settings][sort][field]'); $this->assertFieldByName('field[settings][handler_settings][sort][direction]', 'ASC'); // Test that a non-translatable base field is a sort option. $this->assertFieldByXPath("//select[@name='field[settings][handler_settings][sort][field]']/option[@value='nid']"); // Test that a translatable base field is a sort option. $this->assertFieldByXPath("//select[@name='field[settings][handler_settings][sort][field]']/option[@value='title']"); // Test that a configurable field is a sort option. $this->assertFieldByXPath("//select[@name='field[settings][handler_settings][sort][field]']/option[@value='body.value']"); // Set back to no sort. $this->drupalPostAjaxForm(NULL, array('field[settings][handler_settings][sort][field]' => '_none'), 'field[settings][handler_settings][sort][field]'); $this->assertNoFieldByName('field[settings][handler_settings][sort][direction]'); // Third step: confirm. $this->drupalPostForm(NULL, array('field[required]' => '1', 'field[settings][handler_settings][target_bundles][' . key($bundles) . ']' => key($bundles)), t('Save settings')); // Check that the field appears in the overview form. $this->assertFieldByXPath('//table[@id="field-overview"]//tr[@id="field-test"]/td[1]', 'Test label', 'Field was created and appears in the overview page.'); // Check that the field settings form can be submitted again, even when the // field is required. // The first 'Edit' link is for the Body field. $this->clickLink(t('Edit'), 1); $this->drupalPostForm(NULL, array(), t('Save settings')); // Switch the target type to 'taxonomy_term' and check that the settings // specific to its selection handler are displayed. $field_name = 'node.' . $this->type . '.field_test'; $edit = array('field_storage[settings][target_type]' => 'taxonomy_term'); $this->drupalPostForm($bundle_path . '/fields/' . $field_name . '/storage', $edit, t('Save field settings')); $this->drupalGet($bundle_path . '/fields/' . $field_name); $this->assertFieldByName('field[settings][handler_settings][auto_create]'); // Switch the target type to 'user' and check that the settings specific to // its selection handler are displayed. $field_name = 'node.' . $this->type . '.field_test'; $edit = array('field_storage[settings][target_type]' => 'user'); $this->drupalPostForm($bundle_path . '/fields/' . $field_name . '/storage', $edit, t('Save field settings')); $this->drupalGet($bundle_path . '/fields/' . $field_name); $this->assertFieldByName('field[settings][handler_settings][filter][type]', '_none'); // Try to select the views handler. $edit = array('field[settings][handler]' => 'views'); $this->drupalPostAjaxForm($bundle_path . '/fields/' . $field_name, $edit, 'field[settings][handler]'); $this->drupalPostForm(NULL, $edit, t('Save settings')); $this->assertResponse(200); }
/** * {@inheritdoc} */ public function isTranslatable() { // @todo Inject the entity manager and retrieve bundle info from it. $bundles = entity_get_bundles($this->entityTypeId); return !empty($bundles[$this->bundle()]['translatable']); }
/** * Tests menu link bundles. */ public function testMenuBundles() { $this->drupalLogin($this->admin_user); $menu = $this->addCustomMenu(); // Clear the entity cache to ensure the static caches are rebuilt. \Drupal::entityManager()->clearCachedBundles(); $bundles = entity_get_bundles('menu_link'); $this->assertTrue(isset($bundles[$menu->id()])); $menus = menu_list_system_menus(); $menus[$menu->id()] = $menu->label(); ksort($menus); $this->assertIdentical(array_keys($bundles), array_keys($menus)); // Test if moving a menu link between menus changes the bundle. $node = $this->drupalCreateNode(array('type' => 'article')); $item = $this->addMenuLink(0, 'node/' . $node->id(), 'tools'); $this->moveMenuLink($item, 0, $menu->id()); $this->assertEqual($item->bundle(), 'tools', 'Menu link bundle matches the menu'); $moved_item = entity_load('menu_link', $item->id(), TRUE); $this->assertNotEqual($moved_item->bundle(), $item->bundle(), 'Menu link bundle was changed'); $this->assertEqual($moved_item->bundle(), $menu->id(), 'Menu link bundle matches the menu'); $unsaved_item = entity_create('menu_link', array('menu_name' => $menu->id(), 'link_title' => $this->randomName(16), 'link_path' => '<front>')); $this->assertEqual($unsaved_item->bundle(), $menu->id(), 'Unsaved menu link bundle matches the menu'); $this->assertEqual($unsaved_item->menu_name, $menu->id(), 'Unsaved menu link menu name matches the menu'); }
/** * Creates a new entity from a label entered in the autocomplete input. * * @param string $label * The entity label. * @param int $uid * The entity uid. * * @return \Drupal\Core\Entity\EntityInterface */ protected function createNewEntity($label, $uid) { $entity_manager = \Drupal::entityManager(); $target_type = $this->getFieldSetting('target_type'); $target_bundles = $this->getSelectionHandlerSetting('target_bundles'); // Get the bundle. if (!empty($target_bundles)) { $bundle = reset($target_bundles); } else { $bundles = entity_get_bundles($target_type); $bundle = reset($bundles); } $entity_type = $entity_manager->getDefinition($target_type); $bundle_key = $entity_type->getKey('bundle'); $label_key = $entity_type->getKey('label'); $entity = $entity_manager->getStorage($target_type)->create(array($label_key => $label, $bundle_key => $bundle)); if ($entity instanceof EntityOwnerInterface) { $entity->setOwnerId($uid); } return $entity; }