Issue #2016177 by yched, berdir: Refactor 'autocreate entity' handling from entity_reference().
parent
e56a599e83
commit
cd8a251f5f
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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']));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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']);
|
||||
|
|
|
@ -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'],
|
||||
);
|
||||
|
|
|
@ -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,
|
||||
));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue