/** * Handles the response for inline entity form autocompletion. * * @return \Symfony\Component\HttpFoundation\JsonResponse */ public function autocomplete($entity_type_id, $field_name, $bundle, Request $request) { $string = $request->query->get('q'); $fields = $this->entityManager->getFieldDefinitions($entity_type_id, $bundle); $widget = $this->entityManager->getStorage('entity_form_display')->load($entity_type_id . '.' . $bundle . '.default')->getComponent($field_name); // The path was passed invalid parameters, or the string is empty. // strlen() is used instead of empty() since '0' is a valid value. if (!isset($fields[$field_name]) || !$widget || !strlen($string)) { throw new AccessDeniedHttpException(); } $field = $fields[$field_name]; $results = array(); if ($field->getType() == 'entity_reference') { /** @var \Drupal\Core\Entity\EntityReferenceSelection\SelectionInterface $handler */ $handler = $this->selectionManager->getSelectionHandler($field); $entity_labels = $handler->getReferenceableEntities($string, $widget['settings']['match_operator'], 10); foreach ($entity_labels as $bundle => $labels) { // Loop through each entity type, and autocomplete with its titles. foreach ($labels as $entity_id => $label) { // entityreference has already check_plain-ed the title. $results[] = t('!label (!entity_id)', array('!label' => $label, '!entity_id' => $entity_id)); } } } $matches = array(); foreach ($results as $result) { // Strip things like starting/trailing white spaces, line breaks and tags. $key = preg_replace('/\\s\\s+/', ' ', str_replace("\n", '', trim(Html::decodeEntities(strip_tags($result))))); $matches[] = ['value' => $key, 'label' => '<div class="reference-autocomplete">' . $result . '</div>']; } return new JsonResponse($matches); }
/** * {@inheritdoc} */ public function import(Row $row, array $old_destination_id_values = array()) { if ($bundle_key = $this->getKey('bundle')) { $bundle = $row->getDestinationProperty($bundle_key); } else { $bundle = $this->storage->getEntityTypeId(); } // Some migrations save additional data of an existing entity and only // provide the reference to the entity, in those cases, we can not run the // processing below. Migrations that need that need to provide the bundle. if ($bundle) { $field_definitions = $this->entityManager->getFieldDefinitions($this->storage->getEntityTypeId(), $bundle); foreach ($field_definitions as $field_name => $field_definition) { $field_type = $field_definition->getType(); if ($this->migrateEntityFieldPluginManager->getDefinition($field_type, FALSE)) { $destination_value = $this->migrateEntityFieldPluginManager->createInstance($field_type)->import($field_definition, $row->getDestinationProperty($field_name)); // @TODO: check for NULL return? Add an unset to $row? Maybe needed in // exception handling? Propagate exception? $row->setDestinationProperty($field_name, $destination_value); } } } $entity = $this->getEntity($row, $old_destination_id_values); return $this->save($entity, $old_destination_id_values); }
/** * {@inheritdoc} */ public function load() { $entities = array_filter($this->entityManager->getFieldDefinitions($this->targetEntityTypeId, $this->targetBundle), function ($field_definition) { return $field_definition instanceof FieldConfigInterface; }); // Sort the entities using the entity class's sort() method. // See \Drupal\Core\Config\Entity\ConfigEntityBase::sort(). uasort($entities, array($this->entityType->getClass(), 'sort')); return $entities; }
/** * {@inheritdoc} */ public function save(array $form, FormStateInterface $form_state) { $type = $this->entity; $type->setNewRevision($form_state->getValue(array('options', 'revision'))); $type->type = trim($type->id()); $type->name = trim($type->name); $status = $type->save(); $t_args = array('%name' => $type->label()); if ($status == SAVED_UPDATED) { drupal_set_message(t('The content type %name has been updated.', $t_args)); } elseif ($status == SAVED_NEW) { drupal_set_message(t('The content type %name has been added.', $t_args)); $context = array_merge($t_args, array('link' => $this->l(t('View'), new Url('node.overview_types')))); $this->logger('node')->notice('Added content type %name.', $context); } $fields = $this->entityManager->getFieldDefinitions('node', $type->id()); // Update title field definition. $title_field = $fields['title']; $title_label = $form_state->getValue('title_label'); if ($title_field->getLabel() != $title_label) { $title_field->getConfig($type->id())->setLabel($title_label)->save(); } // Update workflow options. // @todo Make it possible to get default values without an entity. // https://www.drupal.org/node/2318187 $node = $this->entityManager->getStorage('node')->create(array('type' => $type->id())); foreach (array('status', 'promote', 'sticky') as $field_name) { $value = (bool) $form_state->getValue(['options', $field_name]); if ($node->{$field_name}->value != $value) { $fields[$field_name]->getConfig($type->id())->setDefaultValue($value)->save(); } } $this->entityManager->clearCachedFieldDefinitions(); $form_state->setRedirect('node.overview_types'); }
/** * {@inheritdoc} */ public function save(array $form, FormStateInterface $form_state) { $type = $this->entity; $type->type = trim($type->id()); $type->name = trim($type->name); $status = $type->save(); $t_args = array('%name' => $type->label()); if ($status == SAVED_UPDATED) { drupal_set_message(t('The entity bundle %name has been updated.', $t_args)); } elseif ($status == SAVED_NEW) { drupal_set_message(t('The entity bundle %name has been added.', $t_args)); $context = array_merge($t_args, array('link' => $this->l(t('View'), new Url('eck.entity.' . $type->getEntityType()->getBundleOf() . '_type.list')))); $this->logger($this->entity->getEntityTypeId())->notice('Added entity bundle %name.', $context); } $fields = $this->entityManager->getFieldDefinitions($type->getEntityType()->getBundleOf(), $type->id()); // Update title field definition. $title_field = $fields['title']; $title_label = $form_state->getValue('title_label'); if ($title_field->getLabel() != $title_label) { $title_field->getConfig($type->id())->setLabel($title_label)->save(); } // Update workflow options. // @todo Make it possible to get default values without an entity. // https://www.drupal.org/node/2318187 $node = $this->entityManager->getStorage($type->getEntityType()->getBundleOf())->create(array('type' => $type->id())); $this->entityManager->clearCachedFieldDefinitions(); $form_state->setRedirect('eck.entity.' . $type->getEntityType()->getBundleOf() . '_type.list'); }
/** * {@inheritdoc} */ public function save(array $form, FormStateInterface $form_state) { $type = $this->entity; $type->setNewRevision($form_state->getValue(array('options', 'revision'))); $type->set('type', trim($type->id())); $type->set('name', trim($type->label())); $status = $type->save(); $t_args = array('%name' => $type->label()); if ($status == SAVED_UPDATED) { drupal_set_message(t('The content type %name has been updated.', $t_args)); } elseif ($status == SAVED_NEW) { drupal_set_message(t('The content type %name has been added.', $t_args)); $context = array_merge($t_args, array('link' => $type->link($this->t('View'), 'collection'))); $this->logger('log')->notice('Added content type %name.', $context); } $fields = $this->entityManager->getFieldDefinitions('log', $type->id()); // Update title field definition. $title_field = $fields['title']; $title_label = $form_state->getValue('title_label'); // Update workflow options. // @todo Make it possible to get default values without an entity. // https://www.drupal.org/node/2318187 $node = $this->entityManager->getStorage('log')->create(array('type' => $type->id())); $this->entityManager->clearCachedFieldDefinitions(); $form_state->setRedirectUrl($type->urlInfo('collection')); }
/** * Populates as much of the stub row as possible. * * @param \Drupal\migrate\Row $row * The row of data. */ protected function processStubRow(Row $row) { $bundle_key = $this->getKey('bundle'); if ($bundle_key && empty($row->getDestinationProperty($bundle_key))) { if (empty($this->bundles)) { throw new MigrateException('Stubbing failed, no bundles available for entity type: ' . $this->storage->getEntityTypeId()); } $row->setDestinationProperty($bundle_key, reset($this->bundles)); } // Populate any required fields not already populated. $fields = $this->entityManager->getFieldDefinitions($this->storage->getEntityTypeId(), $bundle_key); foreach ($fields as $field_name => $field_definition) { if ($field_definition->isRequired() && is_null($row->getDestinationProperty($field_name))) { // Use the configured default value for this specific field, if any. if ($default_value = $field_definition->getDefaultValueLiteral()) { $values[] = $default_value; } else { // Otherwise, ask the field type to generate a sample value. $field_type = $field_definition->getType(); /** @var \Drupal\Core\Field\FieldItemInterface $field_type_class */ $field_type_class = $this->fieldTypeManager->getPluginClass($field_definition->getType()); $values = $field_type_class::generateSampleValue($field_definition); if (is_null($values)) { // Handle failure to generate a sample value. throw new MigrateException('Stubbing failed, unable to generate value for field ' . $field_name); } } $row->setDestinationProperty($field_name, $values); } } }
/** * {@inheritdoc} */ public function save(array $form, FormStateInterface $form_state) { $type = $this->entity; $type->setNewRevision($form_state->getValue(array('options', 'revision'))); $type->set('type', trim($type->id())); $type->set('name', trim($type->label())); $status = $type->save(); $t_args = array('%name' => $type->label()); if ($status == SAVED_UPDATED) { drupal_set_message(t('The support ticket type %name has been updated.', $t_args)); } elseif ($status == SAVED_NEW) { support_ticket_add_body_field($type); // @todo drupal_set_message(t('The support ticket type %name has been added.', $t_args)); $context = array_merge($t_args, array('link' => $type->link($this->t('View'), 'collection'))); $this->logger('support_ticket')->notice('Added support ticket type %name.', $context); } $fields = $this->entityManager->getFieldDefinitions('support_ticket', $type->id()); // Update title field definition. $title_field = $fields['title']; $title_label = $form_state->getValue('title_label'); if ($title_field->getLabel() != $title_label) { $title_field->getConfig($type->id())->setLabel($title_label)->save(); } // Update workflow options. $support_ticket = $this->entityManager->getStorage('support_ticket')->create(array('support_ticket_type' => $type->id())); foreach (array('status', 'locked') as $field_name) { $value = (bool) $form_state->getValue(['options', $field_name]); if ($support_ticket->{$field_name}->value != $value) { $fields[$field_name]->getConfig($type->id())->setDefaultValue($value)->save(); } } $this->entityManager->clearCachedFieldDefinitions(); $form_state->setRedirectUrl($type->urlInfo('collection')); }
/** * {@inheritdoc} */ public function buildConfigurationForm(array $form, FormStateInterface $form_state) { $entity_type_id = $this->configuration['target_type']; $selection_handler_settings = $this->configuration['handler_settings']; $entity_type = $this->entityManager->getDefinition($entity_type_id); $bundles = $this->entityManager->getBundleInfo($entity_type_id); // Merge-in default values. $selection_handler_settings += array('target_bundles' => NULL, 'sort' => array('field' => '_none'), 'auto_create' => FALSE, 'auto_create_bundle' => NULL); if ($entity_type->hasKey('bundle')) { $bundle_options = array(); foreach ($bundles as $bundle_name => $bundle_info) { $bundle_options[$bundle_name] = $bundle_info['label']; } natsort($bundle_options); $form['target_bundles'] = array('#type' => 'checkboxes', '#title' => $this->t('Bundles'), '#options' => $bundle_options, '#default_value' => (array) $selection_handler_settings['target_bundles'], '#required' => TRUE, '#size' => 6, '#multiple' => TRUE, '#element_validate' => [[get_class($this), 'elementValidateFilter']], '#ajax' => TRUE, '#limit_validation_errors' => []); $form['target_bundles_update'] = ['#type' => 'submit', '#value' => $this->t('Update form'), '#limit_validation_errors' => [], '#attributes' => ['class' => ['js-hide']], '#submit' => [[EntityReferenceItem::class, 'settingsAjaxSubmit']]]; } else { $form['target_bundles'] = array('#type' => 'value', '#value' => array()); } if ($entity_type->isSubclassOf('\\Drupal\\Core\\Entity\\FieldableEntityInterface')) { $fields = array(); foreach (array_keys($bundles) as $bundle) { $bundle_fields = array_filter($this->entityManager->getFieldDefinitions($entity_type_id, $bundle), function ($field_definition) { return !$field_definition->isComputed(); }); foreach ($bundle_fields as $field_name => $field_definition) { /* @var \Drupal\Core\Field\FieldDefinitionInterface $field_definition */ $columns = $field_definition->getFieldStorageDefinition()->getColumns(); // If there is more than one column, display them all, otherwise just // display the field label. // @todo: Use property labels instead of the column name. if (count($columns) > 1) { foreach ($columns as $column_name => $column_info) { $fields[$field_name . '.' . $column_name] = $this->t('@label (@column)', array('@label' => $field_definition->getLabel(), '@column' => $column_name)); } } else { $fields[$field_name] = $this->t('@label', array('@label' => $field_definition->getLabel())); } } } $form['sort']['field'] = array('#type' => 'select', '#title' => $this->t('Sort by'), '#options' => array('_none' => $this->t('- None -')) + $fields, '#ajax' => TRUE, '#limit_validation_errors' => array(), '#default_value' => $selection_handler_settings['sort']['field']); $form['sort']['settings'] = array('#type' => 'container', '#attributes' => array('class' => array('entity_reference-settings')), '#process' => [[EntityReferenceItem::class, 'formProcessMergeParent']]); if ($selection_handler_settings['sort']['field'] != '_none') { // Merge-in default values. $selection_handler_settings['sort'] += array('direction' => 'ASC'); $form['sort']['settings']['direction'] = array('#type' => 'select', '#title' => $this->t('Sort direction'), '#required' => TRUE, '#options' => array('ASC' => $this->t('Ascending'), 'DESC' => $this->t('Descending')), '#default_value' => $selection_handler_settings['sort']['direction']); } } $form['auto_create'] = array('#type' => 'checkbox', '#title' => $this->t("Create referenced entities if they don't already exist"), '#default_value' => $selection_handler_settings['auto_create'], '#weight' => -2); if ($entity_type->hasKey('bundle')) { $bundles = array_intersect_key($bundle_options, array_filter((array) $selection_handler_settings['target_bundles'])); $form['auto_create_bundle'] = ['#type' => 'select', '#title' => $this->t('Store new items in'), '#options' => $bundles, '#default_value' => $selection_handler_settings['auto_create_bundle'], '#access' => count($bundles) > 1, '#states' => ['visible' => [':input[name="settings[handler_settings][auto_create]"]' => ['checked' => TRUE]]], '#weight' => -1]; } return $form; }
/** * {@inheritdoc} */ public function buildConfigurationForm(array $form, FormStateInterface $form_state) { $entity_type_id = $this->configuration['target_type']; $selection_handler_settings = $this->configuration['handler_settings']; $entity_type = $this->entityManager->getDefinition($entity_type_id); $bundles = $this->entityManager->getBundleInfo($entity_type_id); // Merge-in default values. $selection_handler_settings += array('target_bundles' => array(), 'sort' => array('field' => '_none'), 'auto_create' => FALSE); if ($entity_type->hasKey('bundle')) { $bundle_options = array(); foreach ($bundles as $bundle_name => $bundle_info) { $bundle_options[$bundle_name] = $bundle_info['label']; } $form['target_bundles'] = array('#type' => 'checkboxes', '#title' => $this->t('Bundles'), '#options' => $bundle_options, '#default_value' => !empty($selection_handler_settings['target_bundles']) ? $selection_handler_settings['target_bundles'] : array(), '#required' => TRUE, '#size' => 6, '#multiple' => TRUE, '#element_validate' => array('_entity_reference_element_validate_filter')); } else { $form['target_bundles'] = array('#type' => 'value', '#value' => array()); } if ($entity_type->isSubclassOf('\\Drupal\\Core\\Entity\\FieldableEntityInterface')) { $fields = array(); foreach (array_keys($bundles) as $bundle) { $bundle_fields = array_filter($this->entityManager->getFieldDefinitions($entity_type_id, $bundle), function ($field_definition) { return !$field_definition->isComputed(); }); foreach ($bundle_fields as $field_name => $field_definition) { /* @var \Drupal\Core\Field\FieldDefinitionInterface $field_definition */ $columns = $field_definition->getFieldStorageDefinition()->getColumns(); // If there is more than one column, display them all, otherwise just // display the field label. // @todo: Use property labels instead of the column name. if (count($columns) > 1) { foreach ($columns as $column_name => $column_info) { $fields[$field_name . '.' . $column_name] = $this->t('@label (@column)', array('@label' => $field_definition->getLabel(), '@column' => $column_name)); } } else { $fields[$field_name] = $this->t('@label', array('@label' => $field_definition->getLabel())); } } } $form['sort']['field'] = array('#type' => 'select', '#title' => $this->t('Sort by'), '#options' => array('_none' => $this->t('- None -')) + $fields, '#ajax' => TRUE, '#limit_validation_errors' => array(), '#default_value' => $selection_handler_settings['sort']['field']); $form['sort']['settings'] = array('#type' => 'container', '#attributes' => array('class' => array('entity_reference-settings')), '#process' => array('_entity_reference_form_process_merge_parent')); if ($selection_handler_settings['sort']['field'] != '_none') { // Merge-in default values. $selection_handler_settings['sort'] += array('direction' => 'ASC'); $form['sort']['settings']['direction'] = array('#type' => 'select', '#title' => $this->t('Sort direction'), '#required' => TRUE, '#options' => array('ASC' => $this->t('Ascending'), 'DESC' => $this->t('Descending')), '#default_value' => $selection_handler_settings['sort']['direction']); } } return $form; }
/** * Helper method to fetch the field map for an entity type. * * @param EntityTypeInterface $entity_type */ public function getFieldMap(EntityTypeInterface $entity_type) { $map = array(); $bundle_info = $this->entityManager->getBundleInfo($entity_type->id()); foreach ($bundle_info as $bundle_id => $bundle_label) { $definitions = $this->entityManager->getFieldDefinitions($entity_type->id(), $bundle_id); foreach ($definitions as $definition) { $name = $definition->getName(); // We don't want our own fields to be part of the migration mapping or // they would get assigned NULL instead of default values. if (!in_array($name, ['workspace', '_deleted', '_rev'])) { $map[$name] = $name; } } } return $map; }
/** * Writes the cache of relation links. * * @param array $context * Context from the normalizer/serializer operation. */ protected function writeCache($context = array()) { $data = array(); foreach ($this->entityManager->getDefinitions() as $entity_type) { if ($entity_type instanceof ContentEntityTypeInterface) { foreach ($this->entityManager->getBundleInfo($entity_type->id()) as $bundle => $bundle_info) { foreach ($this->entityManager->getFieldDefinitions($entity_type->id(), $bundle) as $field_definition) { $relation_uri = $this->getRelationUri($entity_type->id(), $bundle, $field_definition->getName(), $context); $data[$relation_uri] = array('entity_type' => $entity_type, 'bundle' => $bundle, 'field_name' => $field_definition->getName()); } } } } // These URIs only change when field info changes, so cache it permanently // and only clear it when the fields cache is cleared. $this->cache->set('rest:links:relations', $data, Cache::PERMANENT, array('entity_field_info')); }
/** * {@inheritdoc} */ public function addDefaultField($entity_type, $bundle, $field_name = 'comment', $default_value = CommentItemInterface::OPEN, $comment_type_id = 'comment') { $comment_type_storage = $this->entityManager->getStorage('comment_type'); if ($comment_type = $comment_type_storage->load($comment_type_id)) { if ($comment_type->getTargetEntityTypeId() !== $entity_type) { throw new \InvalidArgumentException(String::format('The given comment type id %id can only be used with the %entity_type entity type', array('%id' => $comment_type_id, '%entity_type' => $entity_type))); } } else { // Silently create the comment-type for the calling code. $comment_type_storage->create(array('id' => $comment_type_id, 'label' => Unicode::ucfirst($comment_type_id), 'target_entity_type_id' => $entity_type, 'description' => 'Default comment field'))->save(); } // Make sure the field doesn't already exist. if (!FieldStorageConfig::loadByName($entity_type, $field_name)) { // Add a default comment field for existing node comments. $field_storage = $this->entityManager->getStorage('field_storage_config')->create(array('entity_type' => $entity_type, 'field_name' => $field_name, 'type' => 'comment', 'translatable' => TRUE, 'settings' => array('comment_type' => $comment_type_id))); // Create the field. $field_storage->save(); } // Make sure the instance doesn't already exist. if (!array_key_exists($field_name, $this->entityManager->getFieldDefinitions($entity_type, $bundle))) { $field = $this->entityManager->getStorage('field_config')->create(array('label' => 'Comments', 'description' => '', 'field_name' => $field_name, 'entity_type' => $entity_type, 'bundle' => $bundle, 'required' => 1, 'default_value' => array(array('status' => $default_value, 'cid' => 0, 'last_comment_name' => '', 'last_comment_timestamp' => 0, 'last_comment_uid' => 0)))); $field->save(); // Assign widget settings for the 'default' form mode. entity_get_form_display($entity_type, $bundle, 'default')->setComponent($field_name, array('type' => 'comment_default', 'weight' => 20))->save(); // The comment field should be hidden in all other form displays. foreach ($this->entityManager->getFormModes($entity_type) as $id => $form_mode) { $display = entity_get_form_display($entity_type, $bundle, $id); // Only update existing displays. if ($display && !$display->isNew()) { $display->removeComponent($field_name)->save(); } } // Set default to display comment list. entity_get_display($entity_type, $bundle, 'default')->setComponent($field_name, array('label' => 'above', 'type' => 'comment_default', 'weight' => 20))->save(); // The comment field should be hidden in all other view displays. foreach ($this->entityManager->getViewModes($entity_type) as $id => $view_mode) { $display = entity_get_display($entity_type, $bundle, $id); // Only update existing displays. if ($display && !$display->isNew()) { $display->removeComponent($field_name)->save(); } } } $this->addBodyField($comment_type_id); }
/** * {@inheritdoc} */ public function getRules() { $rules = []; // Collect all fields of all contact types. $contact_types = $this->entityManager->getStorage('crm_core_contact_type')->loadMultiple(); $field_definitions = []; foreach ($contact_types as $contact_type_id => $value) { $field_definitions += $this->entityManager->getFieldDefinitions('crm_core_contact', $contact_type_id); } foreach ($this->getConfigurationItem('rules') as $field_name => $field_settings) { // Skip fields that are disabled on the matcher. if (empty($field_settings['value']['status'])) { continue; } // Skip fields that got dropped. if (!isset($field_definitions[$field_name])) { continue; } /** @var \Drupal\Core\Field\FieldDefinitionInterface $field_definition */ $field_definition = $field_definitions[$field_name]; $rules[$field_name] = array('label' => $field_definition->getLabel(), 'definition' => $field_definition); } return $rules; }
/** * {@inheritdoc} */ public function onBundleRename($bundle, $bundle_new) { // The method runs before the field definitions are updated, so we use the // old bundle name. $field_definitions = $this->entityManager->getFieldDefinitions($this->entityTypeId, $bundle); // We need to handle deleted fields too. For now, this only makes sense for // configurable fields, so we use the specific API. // @todo Use the unified store of deleted field definitions instead in // https://www.drupal.org/node/2282119 $field_definitions += entity_load_multiple_by_properties('field_instance_config', array('entity_type' => $this->entityTypeId, 'bundle' => $bundle, 'deleted' => TRUE, 'include_deleted' => TRUE)); foreach ($field_definitions as $field_definition) { $storage_definition = $field_definition->getFieldStorageDefinition(); if ($this->usesDedicatedTable($storage_definition)) { $is_deleted = $this->storageDefinitionIsDeleted($storage_definition); $table_name = static::_fieldTableName($storage_definition, $is_deleted); $revision_name = static::_fieldRevisionTableName($storage_definition, $is_deleted); $this->database->update($table_name)->fields(array('bundle' => $bundle_new))->condition('bundle', $bundle)->execute(); $this->database->update($revision_name)->fields(array('bundle' => $bundle_new))->condition('bundle', $bundle)->execute(); } } }
/** * {@inheritdoc} */ public function checkNodeType(NodeInterface $node) { // Fetch information about the forum field. $field_definitions = $this->entityManager->getFieldDefinitions('node', $node->bundle()); return !empty($field_definitions['taxonomy_forums']); }
/** * {@inheritdoc} */ public function getFieldDefinitions($entity_type_id, $bundle) { return $this->entityManager->getFieldDefinitions($entity_type_id, $bundle); }
/** * {@inheritdoc} */ public function getPaymentDescription() { $field_definitions = $this->entityManager->getFieldDefinitions($this->getEntityTypeId(), $this->getBundle()); return isset($field_definitions[$this->getFieldName()]) ? $field_definitions[$this->getFieldName()]->getLabel() : new TranslationWrapper('Unavailable'); }