/**
  * Returns the entity_form_display object used to build an entity form.
  *
  * Depending on the configuration of the form mode for the entity bundle, this
  * can be either the display object associated to the form mode, or the
  * 'default' display.
  *
  * This method should only be used internally when rendering an entity form.
  * When assigning suggested display options for a component in a given form
  * mode, entity_get_form_display() should be used instead, in order to avoid
  * inadvertently modifying the output of other form modes that might happen to
  * use the 'default' display too. Those options will then be effectively
  * applied only if the form mode is configured to use them.
  *
  * hook_entity_form_display_alter() is invoked on each display, allowing 3rd
  * party code to alter the display options held in the display before they are
  * used to generate render arrays.
  *
  * @param \Drupal\Core\Entity\FieldableEntityInterface $entity
  *   The entity for which the form is being built.
  * @param string $form_mode
  *   The form mode.
  *
  * @return \Drupal\Core\Entity\Display\EntityFormDisplayInterface
  *   The display object that should be used to build the entity form.
  *
  * @see entity_get_form_display()
  * @see hook_entity_form_display_alter()
  */
 public static function collectRenderDisplay(FieldableEntityInterface $entity, $form_mode)
 {
     $entity_type = $entity->getEntityTypeId();
     $bundle = $entity->bundle();
     // Check the existence and status of:
     // - the display for the form mode,
     // - the 'default' display.
     if ($form_mode != 'default') {
         $candidate_ids[] = $entity_type . '.' . $bundle . '.' . $form_mode;
     }
     $candidate_ids[] = $entity_type . '.' . $bundle . '.default';
     $results = \Drupal::entityQuery('entity_form_display')->condition('id', $candidate_ids)->condition('status', TRUE)->execute();
     // Load the first valid candidate display, if any.
     $storage = \Drupal::entityManager()->getStorage('entity_form_display');
     foreach ($candidate_ids as $candidate_id) {
         if (isset($results[$candidate_id])) {
             $display = $storage->load($candidate_id);
             break;
         }
     }
     // Else create a fresh runtime object.
     if (empty($display)) {
         $display = $storage->create(array('targetEntityType' => $entity_type, 'bundle' => $bundle, 'mode' => $form_mode, 'status' => TRUE));
     }
     // Let the display know which form mode was originally requested.
     $display->originalMode = $form_mode;
     // Let modules alter the display.
     $display_context = array('entity_type' => $entity_type, 'bundle' => $bundle, 'form_mode' => $form_mode);
     \Drupal::moduleHandler()->alter('entity_form_display', $display, $display_context);
     return $display;
 }
 /**
  * {@inheritdoc}
  */
 public function create(FieldableEntityInterface $entity, $fields)
 {
     $query = $this->database->insert('comment_entity_statistics')->fields(array('entity_id', 'entity_type', 'field_name', 'cid', 'last_comment_timestamp', 'last_comment_name', 'last_comment_uid', 'comment_count'));
     foreach ($fields as $field_name => $detail) {
         // Skip fields that entity does not have.
         if (!$entity->hasField($field_name)) {
             continue;
         }
         // Get the user ID from the entity if it's set, or default to the
         // currently logged in user.
         $last_comment_uid = 0;
         if ($entity instanceof EntityOwnerInterface) {
             $last_comment_uid = $entity->getOwnerId();
         }
         if (!isset($last_comment_uid)) {
             // Default to current user when entity does not implement
             // EntityOwnerInterface or author is not set.
             $last_comment_uid = $this->currentUser->id();
         }
         // Default to REQUEST_TIME when entity does not have a changed property.
         $last_comment_timestamp = REQUEST_TIME;
         // @todo Make comment statistics language aware and add some tests. See
         //   https://www.drupal.org/node/2318875
         if ($entity instanceof EntityChangedInterface) {
             $last_comment_timestamp = $entity->getChangedTimeAcrossTranslations();
         }
         $query->values(array('entity_id' => $entity->id(), 'entity_type' => $entity->getEntityTypeId(), 'field_name' => $field_name, 'cid' => 0, 'last_comment_timestamp' => $last_comment_timestamp, 'last_comment_name' => NULL, 'last_comment_uid' => $last_comment_uid, 'comment_count' => 0));
     }
     $query->execute();
 }
Ejemplo n.º 3
0
/**
 * Provide the allowed values for a 'list_*' field.
 *
 * Callback for options_allowed_values().
 *
 * 'list_*' fields can specify a callback to define the set of their allowed
 * values using the 'allowed_values_function' storage setting.
 *
 * That function will be called:
 *  - either in the context of a specific entity, which is then provided as the
 *    $entity parameter,
 *  - or for the field generally without the context of any specific entity or
 *    entity bundle (typically, Views needing a list of values for an exposed
 *    filter), in which case the $entity parameter is NULL.
 * This lets the callback restrict the set of allowed values or adjust the
 * labels depending on some conditions on the containing entity.
 *
 * For consistency, the set of values returned when an $entity is provided
 * should be a subset of the values returned when no $entity is provided.
 *
 * @param \Drupal\Core\Field\FieldStorageDefinitionInterface $definition
 *   The field storage definition.
 * @param \Drupal\Core\Entity\FieldableEntityInterface|null $entity
 *   (optional) The entity context if known, or NULL if the allowed values are
 *   being collected without the context of a specific entity.
 * @param bool &$cacheable
 *   (optional) If an $entity is provided, the $cacheable parameter should be
 *   modified by reference and set to FALSE if the set of allowed values
 *   returned was specifically adjusted for that entity and cannot not be reused
 *   for other entities. Defaults to TRUE.
 *
 * @return array
 *   The array of allowed values. Keys of the array are the raw stored values
 *   (number or text), values of the array are the display labels. If $entity
 *   is NULL, you should return the list of all the possible allowed values in
 *   any context so that other code (e.g. Views filters) can support the allowed
 *   values for all possible entities and bundles.
 *
 * @ingroup callbacks
 * @see options_allowed_values()
 * @see options_test_allowed_values_callback()
 * @see options_test_dynamic_values_callback()
 */
function callback_allowed_values_function(FieldStorageDefinitionInterface $definition, FieldableEntityInterface $entity = NULL, &$cacheable = TRUE)
{
    if (isset($entity) && $entity->bundle() == 'not_a_programmer') {
        $values = array(1 => 'One', 2 => 'Two');
    } else {
        $values = array('Group 1' => array(0 => 'Zero', 1 => 'One'), 'Group 2' => array(2 => 'Two'));
    }
    return $values;
}
 /**
  * {@inheritdoc}
  */
 public function filterByFieldAccess(AccountInterface $account = NULL)
 {
     $filtered_fields = array();
     foreach ($this->getFieldNames() as $field_name) {
         if (!$this->entity->get($field_name)->access('edit', $account)) {
             $filtered_fields[] = $field_name;
         }
     }
     return $this->filterByFields($filtered_fields);
 }
 /**
  * Checks whether field languages are correctly stored for the given entity.
  *
  * @param \Drupal\Core\Entity\FieldableEntityInterface $entity
  *   The entity fields are attached to.
  * @param string $message
  *   (optional) A message to display with the assertion.
  */
 protected function assertFieldStorageLangcode(FieldableEntityInterface $entity, $message = '')
 {
     $status = TRUE;
     $entity_type = $entity->getEntityTypeId();
     $id = $entity->id();
     $langcode = $entity->getUntranslated()->language()->getId();
     $fields = array($this->field_name, $this->untranslatable_field_name);
     /** @var \Drupal\Core\Entity\Sql\DefaultTableMapping $table_mapping */
     $table_mapping = \Drupal::entityManager()->getStorage($entity_type)->getTableMapping();
     foreach ($fields as $field_name) {
         $field_storage = FieldStorageConfig::loadByName($entity_type, $field_name);
         $table = $table_mapping->getDedicatedDataTableName($field_storage);
         $record = \Drupal::database()->select($table, 'f')->fields('f')->condition('f.entity_id', $id)->condition('f.revision_id', $id)->execute()->fetchObject();
         if ($record->langcode != $langcode) {
             $status = FALSE;
             break;
         }
     }
     return $this->assertTrue($status, $message);
 }
Ejemplo n.º 6
0
 /**
  * {@inheritdoc}
  */
 public function getOptionsProvider($property_name, FieldableEntityInterface $entity)
 {
     // If the field item class implements the interface, create an orphaned
     // runtime item object, so that it can be used as the options provider
     // without modifying the entity being worked on.
     if (is_subclass_of($this->getFieldItemClass(), '\\Drupal\\Core\\TypedData\\OptionsProviderInterface')) {
         $items = $entity->get($this->getName());
         return \Drupal::service('plugin.manager.field.field_type')->createFieldItem($items, 0);
     }
     // @todo: Allow setting custom options provider, see
     // https://www.drupal.org/node/2002138.
 }
 /**
  * {@inheritdoc}
  */
 public function setChangedTime($timestamp)
 {
     $field_name = $this->translation->hasField('content_translation_changed') ? 'content_translation_changed' : 'changed';
     $this->translation->set($field_name, $timestamp);
     return $this;
 }
Ejemplo n.º 8
0
 /**
  * {@inheritdoc}
  */
 public function getOptionsProvider($property_name, FieldableEntityInterface $entity)
 {
     // If the field item class implements the interface, proxy it through.
     $item = $entity->get($this->getName())->first();
     if ($item instanceof OptionsProviderInterface) {
         return $item;
     }
     // @todo: Allow setting custom options provider, see
     // https://www.drupal.org/node/2002138.
 }
 /**
  * Returns the display object used to render an entity.
  *
  * See the collectRenderDisplays() method for details.
  *
  * @param \Drupal\Core\Entity\FieldableEntityInterface $entity
  *   The entity being rendered.
  * @param string $view_mode
  *   The view mode.
  *
  * @return \Drupal\Core\Entity\Display\EntityViewDisplayInterface
  *   The display object that should be used to render the entity.
  *
  * @see \Drupal\entity\Entity\EntityDisplay::collectRenderDisplays()
  */
 public static function collectRenderDisplay(FieldableEntityInterface $entity, $view_mode)
 {
     $displays = static::collectRenderDisplays(array($entity), $view_mode);
     return $displays[$entity->bundle()];
 }
 /**
  * Finds the field name for the field carrying the changed timestamp, if any.
  *
  * @param \Drupal\Core\Entity\FieldableEntityInterface $entity
  *   The entity.
  *
  * @return string|null
  *   The name of the field found or NULL if not found.
  */
 protected function getChangedFieldName(FieldableEntityInterface $entity)
 {
     foreach ($entity->getFieldDefinitions() as $field) {
         if ($field->getType() == 'changed') {
             return $field->getName();
         }
     }
 }
Ejemplo n.º 11
0
 /**
  * {@inheritdoc}
  */
 public function createFieldItemList(FieldableEntityInterface $entity, $field_name, $values = NULL)
 {
     // Leverage prototyping of the Typed Data API for fast instantiation.
     return $this->typedDataManager->getPropertyInstance($entity->getTypedData(), $field_name, $values);
 }
Ejemplo n.º 12
0
 /**
  * {@inheritdoc}
  */
 public function getNewCommentPageNumber($total_comments, $new_comments, FieldableEntityInterface $entity, $field_name)
 {
     $field = $entity->getFieldDefinition($field_name);
     $comments_per_page = $field->getSetting('per_page');
     if ($total_comments <= $comments_per_page) {
         // Only one page of comments.
         $count = 0;
     } elseif ($field->getSetting('default_mode') == CommentManagerInterface::COMMENT_MODE_FLAT) {
         // Flat comments.
         $count = $total_comments - $new_comments;
     } else {
         // Threaded comments.
         // 1. Find all the threads with a new comment.
         $unread_threads_query = $this->database->select('comment_field_data', 'comment')->fields('comment', array('thread'))->condition('entity_id', $entity->id())->condition('entity_type', $entity->getEntityTypeId())->condition('field_name', $field_name)->condition('status', CommentInterface::PUBLISHED)->condition('default_langcode', 1)->orderBy('created', 'DESC')->orderBy('cid', 'DESC')->range(0, $new_comments);
         // 2. Find the first thread.
         $first_thread_query = $this->database->select($unread_threads_query, 'thread');
         $first_thread_query->addExpression('SUBSTRING(thread, 1, (LENGTH(thread) - 1))', 'torder');
         $first_thread = $first_thread_query->fields('thread', array('thread'))->orderBy('torder')->range(0, 1)->execute()->fetchField();
         // Remove the final '/'.
         $first_thread = substr($first_thread, 0, -1);
         // Find the number of the first comment of the first unread thread.
         $count = $this->database->query('SELECT COUNT(*) FROM {comment_field_data} WHERE entity_id = :entity_id
                     AND entity_type = :entity_type
                     AND field_name = :field_name
                     AND status = :status
                     AND SUBSTRING(thread, 1, (LENGTH(thread) - 1)) < :thread
                     AND default_langcode = 1', array(':status' => CommentInterface::PUBLISHED, ':entity_id' => $entity->id(), ':field_name' => $field_name, ':entity_type' => $entity->getEntityTypeId(), ':thread' => $first_thread))->fetchField();
     }
     return $comments_per_page > 0 ? (int) ($count / $comments_per_page) : 0;
 }
Ejemplo n.º 13
0
 /**
  * {@inheritdoc}
  */
 public function buildForm(FieldableEntityInterface $entity, array &$form, FormStateInterface $form_state)
 {
     // Set #parents to 'top-level' by default.
     $form += array('#parents' => array());
     // Let each widget generate the form elements.
     foreach ($this->getComponents() as $name => $options) {
         if ($widget = $this->getRenderer($name)) {
             $items = $entity->get($name);
             $items->filterEmptyItems();
             $form[$name] = $widget->form($items, $form, $form_state);
             $form[$name]['#access'] = $items->access('edit');
             // Assign the correct weight. This duplicates the reordering done in
             // processForm(), but is needed for other forms calling this method
             // directly.
             $form[$name]['#weight'] = $options['weight'];
             // Associate the cache tags for the field definition & field storage
             // definition.
             $field_definition = $this->getFieldDefinition($name);
             $this->renderer->addCacheableDependency($form[$name], $field_definition);
             $this->renderer->addCacheableDependency($form[$name], $field_definition->getFieldStorageDefinition());
         }
     }
     // Associate the cache tags for the form display.
     $this->renderer->addCacheableDependency($form, $this);
     // Add a process callback so we can assign weights and hide extra fields.
     $form['#process'][] = array($this, 'processForm');
 }
Ejemplo n.º 14
0
 /**
  * Checks if a given entity has a given field.
  *
  * @param \Drupal\Core\Entity\FieldableEntityInterface $entity
  *   The entity to check for the provided field.
  * @param string $field
  *   The field to check for on the entity.
  *
  * @return bool
  *   TRUE if the provided entity has the provided field.
  */
 protected function doEvaluate(FieldableEntityInterface $entity, $field)
 {
     return $entity->hasField($field);
 }
Ejemplo n.º 15
0
 /**
  * {@inheritdoc}
  */
 public function validateFormValues(FieldableEntityInterface $entity, array &$form, FormStateInterface $form_state)
 {
     $violations = $entity->validate();
     $violations->filterByFieldAccess();
     // Flag entity level violations.
     foreach ($violations->getEntityViolations() as $violation) {
         /** @var \Symfony\Component\Validator\ConstraintViolationInterface $violation */
         $form_state->setErrorByName('', $violation->getMessage());
     }
     $this->flagWidgetsErrorsFromViolations($violations, $form, $form_state);
 }
 /**
  * Updates a field value, only if the field is translatable.
  *
  * @param string $field_name
  *   The name of the field.
  * @param mixed $value
  *   The field value to be set.
  */
 protected function setFieldOnlyIfTranslatable($field_name, $value)
 {
     if ($this->translation->getFieldDefinition($field_name)->isTranslatable()) {
         $this->translation->set($field_name, $value);
     }
 }
Ejemplo n.º 17
0
 /**
  * {@inheritdoc}
  */
 public function buildCommentedEntityLinks(FieldableEntityInterface $entity, array &$context)
 {
     $entity_links = array();
     $view_mode = $context['view_mode'];
     if ($view_mode == 'search_index' || $view_mode == 'search_result' || $view_mode == 'print' || $view_mode == 'rss') {
         // Do not add any links if the entity is displayed for:
         // - search indexing.
         // - constructing a search result excerpt.
         // - print.
         // - rss.
         return array();
     }
     $fields = $this->commentManager->getFields($entity->getEntityTypeId());
     foreach ($fields as $field_name => $detail) {
         // Skip fields that the entity does not have.
         if (!$entity->hasField($field_name)) {
             continue;
         }
         $links = array();
         $commenting_status = $entity->get($field_name)->status;
         if ($commenting_status != CommentItemInterface::HIDDEN) {
             // Entity has commenting status open or closed.
             $field_definition = $entity->getFieldDefinition($field_name);
             if ($view_mode == 'teaser') {
                 // Teaser view: display the number of comments that have been posted,
                 // or a link to add new comments if the user has permission, the
                 // entity is open to new comments, and there currently are none.
                 if ($this->currentUser->hasPermission('access comments')) {
                     if (!empty($entity->get($field_name)->comment_count)) {
                         $links['comment-comments'] = array('title' => $this->formatPlural($entity->get($field_name)->comment_count, '1 comment', '@count comments'), 'attributes' => array('title' => $this->t('Jump to the first comment.')), 'fragment' => 'comments', 'url' => $entity->urlInfo());
                         if ($this->moduleHandler->moduleExists('history')) {
                             $links['comment-new-comments'] = array('title' => '', 'url' => Url::fromRoute('<current>'), 'attributes' => array('class' => 'hidden', 'title' => $this->t('Jump to the first new comment.'), 'data-history-node-last-comment-timestamp' => $entity->get($field_name)->last_comment_timestamp, 'data-history-node-field-name' => $field_name));
                         }
                     }
                 }
                 // Provide a link to new comment form.
                 if ($commenting_status == CommentItemInterface::OPEN) {
                     $comment_form_location = $field_definition->getSetting('form_location');
                     if ($this->currentUser->hasPermission('post comments')) {
                         $links['comment-add'] = array('title' => $this->t('Add new comments'), 'language' => $entity->language(), 'attributes' => array('title' => $this->t('Share your thoughts and opinions.')), 'fragment' => 'comment-form');
                         if ($comment_form_location == CommentItemInterface::FORM_SEPARATE_PAGE) {
                             $links['comment-add']['url'] = Url::fromRoute('comment.reply', ['entity_type' => $entity->getEntityTypeId(), 'entity' => $entity->id(), 'field_name' => $field_name]);
                         } else {
                             $links['comment-add'] += ['url' => $entity->urlInfo()];
                         }
                     } elseif ($this->currentUser->isAnonymous()) {
                         $links['comment-forbidden'] = array('title' => $this->commentManager->forbiddenMessage($entity, $field_name));
                     }
                 }
             } else {
                 // Entity in other view modes: add a "post comment" link if the user
                 // is allowed to post comments and if this entity is allowing new
                 // comments.
                 if ($commenting_status == CommentItemInterface::OPEN) {
                     $comment_form_location = $field_definition->getSetting('form_location');
                     if ($this->currentUser->hasPermission('post comments')) {
                         // Show the "post comment" link if the form is on another page, or
                         // if there are existing comments that the link will skip past.
                         if ($comment_form_location == CommentItemInterface::FORM_SEPARATE_PAGE || !empty($entity->get($field_name)->comment_count) && $this->currentUser->hasPermission('access comments')) {
                             $links['comment-add'] = array('title' => $this->t('Add new comment'), 'attributes' => array('title' => $this->t('Share your thoughts and opinions.')), 'fragment' => 'comment-form');
                             if ($comment_form_location == CommentItemInterface::FORM_SEPARATE_PAGE) {
                                 $links['comment-add']['url'] = Url::fromRoute('comment.reply', ['entity_type' => $entity->getEntityTypeId(), 'entity' => $entity->id(), 'field_name' => $field_name]);
                             } else {
                                 $links['comment-add']['url'] = $entity->urlInfo();
                             }
                         }
                     } elseif ($this->currentUser->isAnonymous()) {
                         $links['comment-forbidden'] = array('title' => $this->commentManager->forbiddenMessage($entity, $field_name));
                     }
                 }
             }
         }
         if (!empty($links)) {
             $entity_links['comment__' . $field_name] = array('#theme' => 'links__entity__comment__' . $field_name, '#links' => $links, '#attributes' => array('class' => array('links', 'inline')));
             if ($view_mode == 'teaser' && $this->moduleHandler->moduleExists('history') && $this->currentUser->isAuthenticated()) {
                 $entity_links['comment__' . $field_name]['#cache']['contexts'][] = 'user';
                 $entity_links['comment__' . $field_name]['#attached']['library'][] = 'comment/drupal.node-new-comments-link';
                 // Embed the metadata for the "X new comments" link (if any) on this
                 // entity.
                 $entity_links['comment__' . $field_name]['#attached']['drupalSettings']['history']['lastReadTimestamps'][$entity->id()] = (int) history_read($entity->id());
                 $new_comments = $this->commentManager->getCountNewComments($entity);
                 if ($new_comments > 0) {
                     $page_number = $this->entityManager->getStorage('comment')->getNewCommentPageNumber($entity->{$field_name}->comment_count, $new_comments, $entity, $field_name);
                     $query = $page_number ? ['page' => $page_number] : NULL;
                     $value = ['new_comment_count' => (int) $new_comments, 'first_new_comment_link' => $entity->url('canonical', ['query' => $query, 'fragment' => 'new'])];
                     $parents = ['comment', 'newCommentsLinks', $entity->getEntityTypeId(), $field_name, $entity->id()];
                     NestedArray::setValue($entity_links['comment__' . $field_name]['#attached']['drupalSettings'], $parents, $value);
                 }
             }
         }
     }
     return $entity_links;
 }
Ejemplo n.º 18
0
 /**
  * @inheritdoc
  */
 public static function getDefaultAllValue(FieldableEntityInterface $entity, FieldDefinitionInterface $definition)
 {
     // @TODO: This may become configurable.
     $item = FALSE;
     switch ($entity->getEntityType()) {
         case 'user':
         case 'node':
             $item = FALSE;
             break;
         default:
             break;
     }
     return $item;
 }