Issue #2016177 by yched, berdir: Refactor 'autocreate entity' handling from entity_reference().

8.0.x
Alex Pott 2013-06-14 15:45:18 +02:00
parent e56a599e83
commit cd8a251f5f
8 changed files with 59 additions and 49 deletions

View File

@ -93,7 +93,7 @@ function entity_reference_get_selection_handler($field, $instance, EntityInterfa
* Implements hook_field_is_empty().
*/
function entity_reference_field_is_empty($item, $field) {
if (!empty($item['target_id']) && $item['target_id'] == 'auto_create') {
if (empty($item['target_id']) && !empty($item['entity']) && $item['entity']->isNew()) {
// Allow auto-create entities.
return FALSE;
}
@ -106,44 +106,21 @@ function entity_reference_field_is_empty($item, $field) {
* Create an entity on the fly.
*/
function entity_reference_field_presave(EntityInterface $entity, $field, $instance, $langcode, &$items) {
global $user;
$target_type = $field['settings']['target_type'];
$entity_info = entity_get_info($target_type);
$bundles = entity_get_bundles($target_type);
// Get the bundle.
if (!empty($instance['settings']['handler_settings']['target_bundles']) && count($instance['settings']['handler_settings']['target_bundles']) == 1) {
$bundle = reset($instance['settings']['handler_settings']['target_bundles']);
}
else {
$bundle = reset($bundles);
}
foreach ($items as $delta => $item) {
if ($item['target_id'] == 'auto_create') {
$bundle_key = $entity_info['entity_keys']['bundle'];
$label_key = $entity_info['entity_keys']['label'];
$values = array(
$label_key => $item['label'],
$bundle_key => $bundle,
// @todo: Use wrapper to get the user if exists or needed.
'uid' => isset($entity->uid) ? $entity->uid : $user->uid,
);
$target_entity = entity_create($target_type, $values);
$target_entity->save();
$items[$delta]['target_id'] = $target_entity->id();
if (empty($item['target_id']) && !empty($item['entity']) &&$item['entity']->isNew()) {
$item['entity']->save();
$items[$delta]['target_id'] = $item['entity']->id();
}
}
}
/**
* Implements hook_field_validate().
*/
function entity_reference_field_validate(EntityInterface $entity = NULL, $field, $instance, $langcode, $items, &$errors) {
$ids = array();
foreach ($items as $delta => $item) {
if ($item['target_id'] !== 'auto_create' && !entity_reference_field_is_empty($item, $field)) {
if (!empty($item['target_id']) && !$item['entity'] && !$item['entity']->isNew()) {
$ids[$item['target_id']] = $delta;
}
}

View File

@ -95,7 +95,7 @@ class EntityReferenceEntityFormatter extends EntityReferenceFormatterBase {
throw new RecursiveRenderingException(format_string('Recursive rendering detected when rendering entity @entity_type(@entity_id). Aborting rendering.', array('@entity_type' => $entity_type, '@entity_id' => $item['target_id'])));
}
if (!empty($item['entity'])) {
if (!empty($item['target_id'])) {
$entity = clone $item['entity'];
unset($entity->content);
$elements[$delta] = entity_view($entity, $view_mode, $langcode);
@ -107,7 +107,7 @@ class EntityReferenceEntityFormatter extends EntityReferenceFormatterBase {
}
else {
// This is an "auto_create" item.
$elements[$delta] = array('#markup' => $item['label']);
$elements[$delta] = array('#markup' => $entity->label());
}
$depth = 0;
}

View File

@ -64,7 +64,7 @@ abstract class EntityReferenceFormatterBase extends FormatterBase {
foreach ($items[$id] as $delta => $item) {
// If we have a revision ID, the key uses it as well.
$identifier = !empty($item['revision_id']) ? $item['target_id'] . ':' . $item['revision_id'] : $item['target_id'];
if ($item['target_id'] != 'auto_create') {
if ($item['target_id'] !== 0) {
if (!isset($target_entities[$identifier])) {
// The entity no longer exists, so remove the key.
$rekey = TRUE;
@ -80,11 +80,7 @@ abstract class EntityReferenceFormatterBase extends FormatterBase {
}
}
else {
// This is an "auto_create" item, so allow access to it, as the entity
// doesn't exists yet, and we are probably in a preview.
$items[$id][$delta]['entity'] = FALSE;
// Add the label as a special key, as we cannot use entity_label().
$items[$id][$delta]['label'] = $item['label'];
// This is an "auto_create" item, just leave the entity in place.
}
// Mark item as accessible.

View File

@ -34,7 +34,7 @@ class EntityReferenceIdFormatter extends EntityReferenceFormatterBase {
$elements = array();
foreach ($items as $delta => $item) {
if (!empty($item['entity'])) {
if (!empty($item['entity']) && !empty($item['target_id'])) {
$elements[$delta] = array('#markup' => check_plain($item['target_id']));
}
}

View File

@ -78,10 +78,6 @@ class EntityReferenceLabelFormatter extends EntityReferenceFormatterBase {
$elements[$delta] = array('#markup' => check_plain($label));
}
}
else {
// This is an "auto_create" item.
$elements[$delta] = array('#markup' => $item['label']);
}
}
return $elements;

View File

@ -44,19 +44,18 @@ class AutocompleteTagsWidget extends AutocompleteWidgetBase {
$auto_create = isset($this->instance['settings']['handler_settings']['auto_create']) ? $this->instance['settings']['handler_settings']['auto_create'] : FALSE;
if (!empty($element['#value'])) {
$entities = drupal_explode_tags($element['#value']);
$value = array();
foreach ($entities as $entity) {
foreach (drupal_explode_tags($element['#value']) as $input) {
$match = FALSE;
// Take "label (entity id)', match the id from parenthesis.
if (preg_match("/.+\((\d+)\)/", $entity, $matches)) {
if (preg_match("/.+\((\d+)\)/", $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($entity, $element, $form_state, $form, !$auto_create);
$match = $handler->validateAutocompleteInput($input, $element, $form_state, $form, !$auto_create);
}
if ($match) {
@ -64,10 +63,13 @@ class AutocompleteTagsWidget extends AutocompleteWidgetBase {
}
elseif ($auto_create && (count($this->instance['settings']['handler_settings']['target_bundles']) == 1 || count($bundles) == 1)) {
// Auto-create item. see entity_reference_field_presave().
$value[] = array('target_id' => 'auto_create', 'label' => $entity);
$value[] = array(
'target_id' => 0,
'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']);

View File

@ -76,8 +76,8 @@ class AutocompleteWidget extends AutocompleteWidgetBase {
if (!$value && $auto_create && (count($this->instance['settings']['handler_settings']['target_bundles']) == 1)) {
// Auto-create item. see entity_reference_field_presave().
$value = array(
'target_id' => 'auto_create',
'label' => $element['#value'],
'target_id' => 0,
'entity' => $this->createNewEntity($element['#value'], $element['#autocreate_uid']),
// Keep the weight property.
'_weight' => $element['#weight'],
);

View File

@ -53,6 +53,8 @@ abstract class AutocompleteWidgetBase extends WidgetBase {
* Implements \Drupal\field\Plugin\Type\Widget\WidgetInterface::formElement().
*/
public function formElement(array $items, $delta, array $element, $langcode, array &$form, array &$form_state) {
global $user;
$instance = $this->instance;
$field = $this->field;
$entity = isset($element['#entity']) ? $element['#entity'] : NULL;
@ -77,6 +79,8 @@ abstract class AutocompleteWidgetBase extends WidgetBase {
'#size' => $this->getSetting('size'),
'#placeholder' => $this->getSetting('placeholder'),
'#element_validate' => array(array($this, 'elementValidate')),
// @todo: Use wrapper to get the user if exists or needed.
'#autocreate_uid' => isset($entity->uid) ? $entity->uid : $user->uid,
);
return array('target_id' => $element);
@ -120,4 +124,39 @@ abstract class AutocompleteWidgetBase extends WidgetBase {
}
return $entity_labels;
}
/**
* 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->field['settings']['target_type'];
// Get the bundle.
if (!empty($this->instance['settings']['handler_settings']['target_bundles']) && count($this->instance['settings']['handler_settings']['target_bundles']) == 1) {
$bundle = reset($this->instance['settings']['handler_settings']['target_bundles']);
}
else {
$bundles = entity_get_bundles($target_type);
$bundle = reset($bundles);
}
$entity_info = $entity_manager->getDefinition($target_type);
$bundle_key = $entity_info['entity_keys']['bundle'];
$label_key = $entity_info['entity_keys']['label'];
return $entity_manager->getStorageController($target_type)->create(array(
$label_key => $label,
$bundle_key => $bundle,
'uid' => $uid,
));
}
}