/** * {@inheritdoc} */ public function settingsForm(array $form, FormStateInterface $form_state) { $options = array(); $types = NodeType::loadMultiple(); $comment_fields = $this->commentManager ? $this->commentManager->getFields('node') : array(); $map = array($this->t('Hidden'), $this->t('Closed'), $this->t('Open')); foreach ($types as $type) { $options[$type->id()] = array('type' => array('#markup' => $this->t($type->label()))); if ($this->commentManager) { $fields = array(); foreach ($comment_fields as $field_name => $info) { // Find all comment fields for the bundle. if (in_array($type->id(), $info['bundles'])) { $instance = FieldConfig::loadByName('node', $type->id(), $field_name); $default_mode = reset($instance->default_value); $fields[] = SafeMarkup::format('@field: !state', array('@field' => $instance->label(), '!state' => $map[$default_mode['status']])); } } // @todo Refactor display of comment fields. if (!empty($fields)) { $options[$type->id()]['comments'] = array('data' => array('#theme' => 'item_list', '#items' => $fields)); } else { $options[$type->id()]['comments'] = $this->t('No comment fields'); } } } if (empty($options)) { $create_url = $this->urlGenerator->generateFromRoute('node.type_add'); $this->setMessage($this->t('You do not have any content types that can be generated. <a href="@create-type">Go create a new content type</a> already!</a>', array('@create-type' => $create_url)), 'error', FALSE); return; } $header = array('type' => $this->t('Content type')); if ($this->commentManager) { $header['comments'] = array('data' => $this->t('Comments'), 'class' => array(RESPONSIVE_PRIORITY_MEDIUM)); } $form['node_types'] = array('#type' => 'tableselect', '#header' => $header, '#options' => $options); $form['kill'] = array('#type' => 'checkbox', '#title' => $this->t('<strong>Delete all content</strong> in these content types before generating new content.'), '#default_value' => $this->getSetting('kill')); $form['num'] = array('#type' => 'textfield', '#title' => $this->t('How many nodes would you like to generate?'), '#default_value' => $this->getSetting('num'), '#size' => 10); $options = array(1 => $this->t('Now')); foreach (array(3600, 86400, 604800, 2592000, 31536000) as $interval) { $options[$interval] = \Drupal::service('date.formatter')->formatInterval($interval, 1) . ' ' . $this->t('ago'); } $form['time_range'] = array('#type' => 'select', '#title' => $this->t('How far back in time should the nodes be dated?'), '#description' => $this->t('Node creation dates will be distributed randomly from the current time, back to the selected time.'), '#options' => $options, '#default_value' => 604800); $form['max_comments'] = array('#type' => $this->moduleHandler->moduleExists('comment') ? 'textfield' : 'value', '#title' => $this->t('Maximum number of comments per node.'), '#description' => $this->t('You must also enable comments for the content types you are generating. Note that some nodes will randomly receive zero comments. Some will receive the max.'), '#default_value' => $this->getSetting('max_comments'), '#size' => 3, '#access' => $this->moduleHandler->moduleExists('comment')); $form['title_length'] = array('#type' => 'textfield', '#title' => $this->t('Maximum number of words in titles'), '#default_value' => $this->getSetting('title_length'), '#size' => 10); $form['add_alias'] = array('#type' => 'checkbox', '#disabled' => !$this->moduleHandler->moduleExists('path'), '#description' => $this->t('Requires path.module'), '#title' => $this->t('Add an url alias for each node.'), '#default_value' => FALSE); $form['add_statistics'] = array('#type' => 'checkbox', '#title' => $this->t('Add statistics for each node (node_counter table).'), '#default_value' => TRUE, '#access' => $this->moduleHandler->moduleExists('statistics')); $options = array(); // We always need a language $languages = \Drupal::languageManager()->getLanguages(LanguageInterface::STATE_ALL); foreach ($languages as $langcode => $language) { $options[$langcode] = $language->getName(); } $default_language = \Drupal::service('language.default')->get(); $default_langcode = $default_language->getId(); $form['add_language'] = array('#type' => 'select', '#title' => $this->t('Set language on nodes'), '#multiple' => TRUE, '#description' => $this->t('Requires locale.module'), '#options' => $options, '#default_value' => array($default_langcode)); $form['submit'] = array('#type' => 'submit', '#value' => $this->t('Generate'), '#tableselect' => TRUE); $form['#redirect'] = FALSE; return $form; }
/** * Access check for the reply form. * * @param \Drupal\Core\Entity\EntityInterface $entity * The entity this comment belongs to. * @param string $field_name * The field_name to which the comment belongs. * @param int $pid * (optional) Some comments are replies to other comments. In those cases, * $pid is the parent comment's comment ID. Defaults to NULL. * * @throws \Symfony\Component\HttpKernel\Exception\NotFoundHttpException * @return \Drupal\Core\Access\AccessResultInterface * An access result */ public function replyFormAccess(EntityInterface $entity, $field_name, $pid = NULL) { // Check if entity and field exists. $fields = $this->commentManager->getFields($entity->getEntityTypeId()); if (empty($fields[$field_name])) { throw new NotFoundHttpException(); } $account = $this->currentUser(); // Check if the user has the proper permissions. $access = AccessResult::allowedIfHasPermission($account, 'post comments'); $status = $entity->{$field_name}->status; $access = $access->andIf(AccessResult::allowedIf($status == CommentItemInterface::OPEN)->cacheUntilEntityChanges($entity)); // $pid indicates that this is a reply to a comment. if ($pid) { // Check if the user has the proper permissions. $access = $access->andIf(AccessResult::allowedIfHasPermission($account, 'access comments')); /// Load the parent comment. $comment = $this->entityManager()->getStorage('comment')->load($pid); // Check if the parent comment is published and belongs to the entity. $access = $access->andIf(AccessResult::allowedIf($comment && $comment->isPublished() && $comment->getCommentedEntityId() == $entity->id())); if ($comment) { $access->cacheUntilEntityChanges($comment); } } return $access; }
/** * Form constructor for the comment reply form. * * There are several cases that have to be handled, including: * - replies to comments * - replies to entities * - attempts to reply to entities that can no longer accept comments * - respecting access permissions ('access comments', 'post comments', * etc.) * * @param \Symfony\Component\HttpFoundation\Request $request * The current request object. * @param \Drupal\Core\Entity\EntityInterface $entity * The entity this comment belongs to. * @param string $field_name * The field_name to which the comment belongs. * @param int $pid * (optional) Some comments are replies to other comments. In those cases, * $pid is the parent comment's comment ID. Defaults to NULL. * * @throws \Symfony\Component\HttpKernel\Exception\NotFoundHttpException * @return array|\Symfony\Component\HttpFoundation\RedirectResponse * One of the following: * An associative array containing: * - An array for rendering the entity or parent comment. * - comment_entity: If the comment is a reply to the entity. * - comment_parent: If the comment is a reply to another comment. * - comment_form: The comment form as a renderable array. * - A redirect response to current node: * - If user is not authorized to post comments. * - If parent comment doesn't belong to current entity. * - If user is not authorized to view comments. * - If current entity comments are disable. */ public function getReplyForm(Request $request, EntityInterface $entity, $field_name, $pid = NULL) { // Check if entity and field exists. $fields = $this->commentManager->getFields($entity->getEntityTypeId()); if (empty($fields[$field_name])) { throw new NotFoundHttpException(); } $account = $this->currentUser(); $uri = $entity->urlInfo()->setAbsolute(); $build = array(); // Check if the user has the proper permissions. if (!$account->hasPermission('post comments')) { drupal_set_message($this->t('You are not authorized to post comments.'), 'error'); return new RedirectResponse($uri->toString()); } // The user is not just previewing a comment. if ($request->request->get('op') != $this->t('Preview')) { $status = $entity->{$field_name}->status; if ($status != CommentItemInterface::OPEN) { drupal_set_message($this->t("This discussion is closed: you can't post new comments."), 'error'); return new RedirectResponse($uri->toString()); } // $pid indicates that this is a reply to a comment. if ($pid) { // Check if the user has the proper permissions. if (!$account->hasPermission('access comments')) { drupal_set_message($this->t('You are not authorized to view comments.'), 'error'); return new RedirectResponse($uri->toString()); } // Load the parent comment. $comment = $this->entityManager()->getStorage('comment')->load($pid); // Check if the parent comment is published and belongs to the entity. if (!$comment->isPublished() || $comment->getCommentedEntityId() != $entity->id()) { drupal_set_message($this->t('The comment you are replying to does not exist.'), 'error'); return new RedirectResponse($uri->toString()); } // Display the parent comment. $build['comment_parent'] = $this->entityManager()->getViewBuilder('comment')->view($comment); } elseif ($entity->access('view', $account)) { // We make sure the field value isn't set so we don't end up with a // redirect loop. $entity = clone $entity; $entity->{$field_name}->status = CommentItemInterface::HIDDEN; // Render array of the entity full view mode. $build['commented_entity'] = $this->entityManager()->getViewBuilder($entity->getEntityTypeId())->view($entity, 'full'); unset($build['commented_entity']['#cache']); } } else { $build['#title'] = $this->t('Preview comment'); } // Show the actual reply box. $comment = $this->entityManager()->getStorage('comment')->create(array('entity_id' => $entity->id(), 'pid' => $pid, 'entity_type' => $entity->getEntityTypeId(), 'field_name' => $field_name)); $build['comment_form'] = $this->entityFormBuilder()->getForm($comment); return $build; }
/** * {@inheritdoc} */ public function buildForm(array $form, FormStateInterface $form_state) { $comments = $this->queryFactory->get('comment')->condition('comment_type', $this->entity->id())->execute(); $entity_type = $this->entity->getTargetEntityTypeId(); $caption = ''; foreach (array_keys($this->commentManager->getFields($entity_type)) as $field_name) { /** @var \Drupal\field\FieldStorageConfigInterface $field_storage */ if (($field_storage = FieldStorageConfig::loadByName($entity_type, $field_name)) && $field_storage->getSetting('comment_type') == $this->entity->id() && !$field_storage->isDeleted()) { $caption .= '<p>' . $this->t('%label is used by the %field field on your site. You can not remove this comment type until you have removed the field.', array('%label' => $this->entity->label(), '%field' => $field_storage->label())) . '</p>'; } } if (!empty($comments)) { $caption .= '<p>' . $this->formatPlural(count($comments), '%label is used by 1 comment on your site. You can not remove this comment type until you have removed all of the %label comments.', '%label is used by @count comments on your site. You may not remove %label until you have removed all of the %label comments.', array('%label' => $this->entity->label())) . '</p>'; } if ($caption) { $form['description'] = array('#markup' => $caption); return $form; } else { return parent::buildForm($form, $form_state); } }
/** * {@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; }