/**
  * Checks access to the support_ticket preview page.
  *
  * @param \Drupal\Core\Session\AccountInterface $account
  *   The currently logged in account.
  * @param \Drupal\support_ticket\SupportTicketInterface $support_ticket_preview
  *   The support_ticket that is being previewed.
  *
  * @return string
  *   A \Drupal\Core\Access\AccessInterface constant value.
  */
 public function access(AccountInterface $account, SupportTicketInterface $support_ticket_preview)
 {
     if ($support_ticket_preview->isNew()) {
         $access_controller = $this->entityManager->getAccessControlHandler('support_ticket');
         return $access_controller->createAccess($support_ticket_preview->bundle(), $account, [], TRUE);
     } else {
         return $support_ticket_preview->access('update', $account, TRUE);
     }
 }
 /**
  * Build the default links (Read more) for a support ticket.
  *
  * @param \Drupal\support_ticket\SupportTicketInterface $entity
  *   The support ticket object.
  * @param string $view_mode
  *   A view mode identifier.
  *
  * @return array
  *   An array that can be processed by drupal_pre_render_links().
  */
 protected static function buildLinks(SupportTicketInterface $entity, $view_mode)
 {
     $links = array();
     // Always display a read more link on teasers because we have no way
     // to know when a teaser view is different than a full view.
     if ($view_mode == 'teaser') {
         $support_ticket_title_stripped = strip_tags($entity->label());
         $links['support_ticket-readmore'] = array('title' => t('Read more<span class="visually-hidden"> about @title</span>', array('@title' => $support_ticket_title_stripped)), 'url' => $entity->urlInfo(), 'language' => $entity->language(), 'attributes' => array('rel' => 'tag', 'title' => $support_ticket_title_stripped));
     }
     return array('#theme' => 'links__support_ticket__support_ticket', '#links' => $links, '#attributes' => array('class' => array('links', 'inline')));
 }
 /**
  * {@inheritdoc}
  */
 public function submitForm(array &$form, FormStateInterface $form_state)
 {
     $this->supportTicketStorage->deleteRevision($this->revision->getRevisionId());
     $this->logger('content')->notice('@type: deleted %title revision %revision.', array('@type' => $this->revision->bundle(), '%title' => $this->revision->label(), '%revision' => $this->revision->getRevisionId()));
     $support_ticket_type = $this->supportTicketTypeStorage->load($this->revision->bundle())->label();
     drupal_set_message(t('Revision from %revision-date of @type %title has been deleted.', array('%revision-date' => format_date($this->revision->getRevisionCreationTime()), '@type' => $support_ticket_type, '%title' => $this->revision->label())));
     $form_state->setRedirect('entity.support_ticket.canonical', array('support_ticket' => $this->revision->id()));
     if ($this->connection->query('SELECT COUNT(DISTINCT vid) FROM {support_ticket_field_revision} WHERE stid = :stid', array(':stid' => $this->revision->id()))->fetchField() > 1) {
         $form_state->setRedirect('entity.support_ticket.version_history', array('support_ticket' => $this->revision->id()));
     }
 }
 /**
  * Checks support_ticket revision access.
  *
  * @param \Drupal\support_ticket\SupportTicketInterface $support_ticket
  *   The support_ticket to check.
  * @param \Drupal\Core\Session\AccountInterface $account
  *   A user object representing the user for whom the operation is to be
  *   performed.
  * @param string $op
  *   (optional) The specific operation being checked. Defaults to 'view.'
  *
  * @return bool
  *   TRUE if the operation may be performed, FALSE otherwise.
  */
 public function checkAccess(SupportTicketInterface $support_ticket, AccountInterface $account, $op = 'view')
 {
     $map = array('view' => 'view all revisions', 'update' => 'revert all revisions', 'delete' => 'delete all revisions');
     $bundle = $support_ticket->bundle();
     $type_map = array('view' => "view {$bundle} revisions", 'update' => "revert {$bundle} revisions", 'delete' => "delete {$bundle} revisions");
     if (!$support_ticket || !isset($map[$op]) || !isset($type_map[$op])) {
         // If there was no support_ticket to check against, or the $op was not one of
         // the supported ones, we return access denied.
         return FALSE;
     }
     // Statically cache access by revision ID, language code, user account ID,
     // and operation.
     $langcode = $support_ticket->language()->getId();
     $cid = $support_ticket->getRevisionId() . ':' . $langcode . ':' . $account->id() . ':' . $op;
     if (!isset($this->access[$cid])) {
         // Perform basic permission checks first.
         if (!$account->hasPermission($map[$op]) && !$account->hasPermission($type_map[$op]) && !$account->hasPermission('administer support tickets')) {
             $this->access[$cid] = FALSE;
             return FALSE;
         }
         // There should be at least two revisions. If the vid of the given
         // support_ticket and the vid of the default revision differ, then we already
         // have two different revisions so there is no need for a separate database
         // check. Also, if you try to revert to or delete the default revision, that's
         // not good.
         if ($support_ticket->isDefaultRevision() && ($this->supportTicketStorage->countDefaultLanguageRevisions($support_ticket) == 1 || $op == 'update' || $op == 'delete')) {
             $this->access[$cid] = FALSE;
         } elseif ($account->hasPermission('administer support tickets')) {
             $this->access[$cid] = TRUE;
         } else {
             // First check the access to the default revision and finally, if the
             // support_ticket passed in is not the default revision then access to that,
             // too.
             $this->access[$cid] = $this->supportTicketAccess->access($this->supportTicketStorage->load($support_ticket->id()), $op, $account) && ($support_ticket->isDefaultRevision() || $this->supportTicketAccess->access($support_ticket, $op, $account));
         }
     }
     return $this->access[$cid];
 }
/**
 * Alter the links of a support ticket.
 *
 * @param array &$links
 *   A renderable array representing the support ticket links.
 * @param \Drupal\support_ticket\SupportTicketInterface $entity
 *   The support ticket being rendered.
 * @param array &$context
 *   Various aspects of the context in which the support ticket links are going to be
 *   displayed, with the following keys:
 *   - 'view_mode': the view mode in which the support ticket is being viewed
 *   - 'langcode': the language in which the support ticket is being viewed
 *
 * @see \Drupal\support_ticket\SupportTicketViewBuilder::renderLinks()
 * @see \Drupal\support_ticket\SupportTicketViewBuilder::buildLinks()
 * @see entity_crud
 */
function hook_support_ticket_links_alter(array &$links, SupportTicketInterface $entity, array &$context)
{
    $links['mymodule'] = array('#theme' => 'links__support_ticket__mymodule', '#attributes' => array('class' => array('links', 'inline')), '#links' => array('support_ticket-report' => array('title' => t('Report'), 'href' => "support_ticket/{$entity->id()}/report", 'query' => array('token' => \Drupal::getContainer()->get('csrf_token')->get("support_ticket/{$entity->id()}/report")))));
}
 /**
  * {@inheritdoc}
  */
 public function countDefaultLanguageRevisions(SupportTicketInterface $support_ticket)
 {
     return $this->database->query('SELECT COUNT(*) FROM {support_ticket_field_revision} WHERE stid = :stid AND default_langcode = 1', array(':stid' => $support_ticket->id()))->fetchField();
 }
 /**
  * Entity builder updating the support_ticket status with the submitted value.
  *
  * @param string $entity_type_id
  *   The entity type identifier.
  * @param \Drupal\support_ticket\SupportTicketInterface $support_ticket
  *   The support_ticket updated with the submitted values.
  * @param array $form
  *   The complete form array.
  * @param \Drupal\Core\Form\FormStateInterface $form_state
  *   The current state of the form.
  *
  * @see \Drupal\support_ticket\SupportTicketForm::form()
  */
 function updateStatus($entity_type_id, SupportTicketInterface $support_ticket, array $form, FormStateInterface $form_state)
 {
     $element = $form_state->getTriggeringElement();
     if (isset($element['#published_status'])) {
         $support_ticket->setPublished($element['#published_status']);
     }
 }
 /**
  * Prepares a revision to be reverted.
  *
  * @param \Drupal\support_ticket\SupportTicketInterface $revision
  *   The revision to be reverted.
  *
  * @return \Drupal\support_ticket\SupportTicketInterface
  *   The prepared revision ready to be stored.
  */
 protected function prepareRevertedRevision(SupportTicketInterface $revision)
 {
     /** @var \Drupal\support_ticket\SupportTicketInterface $default_revision */
     $default_revision = $this->supportTicketStorage->load($revision->id());
     // If the entity is translated, make sure only translations affected by the
     // specified revision are reverted.
     $languages = $default_revision->getTranslationLanguages();
     if (count($languages) > 1) {
         foreach ($languages as $langcode => $language) {
             if ($revision->hasTranslation($langcode) && !$revision->getTranslation($langcode)->isRevisionTranslationAffected()) {
                 $revision_translation = $revision->getTranslation($langcode);
                 $default_translation = $default_revision->getTranslation($langcode);
                 foreach ($default_revision->getFieldDefinitions() as $field_name => $definition) {
                     if ($definition->isTranslatable()) {
                         $revision_translation->set($field_name, $default_translation->get($field_name)->getValue());
                     }
                 }
             }
         }
     }
     $revision->setNewRevision();
     $revision->isDefaultRevision(TRUE);
     return $revision;
 }
 /**
  * Generates an overview table of older revisions of a support ticket.
  *
  * @param \Drupal\support_ticket\SupportTicketInterface $support_ticket
  *   A support_ticket object.
  *
  * @return array
  *   An array as expected by drupal_render().
  */
 public function revisionOverview(SupportTicketInterface $support_ticket)
 {
     $account = $this->currentUser();
     $support_ticket_storage = $this->entityManager()->getStorage('support_ticket');
     $type = $support_ticket->getType();
     $build = array();
     $build['#title'] = $this->t('Revisions for %title', array('%title' => $support_ticket->label()));
     $header = array($this->t('Revision'), $this->t('Operations'));
     $revert_permission = ($account->hasPermission("revert {$type} revisions") || $account->hasPermission('revert all revisions') || $account->hasPermission('administer support tickets')) && $support_ticket->access('update');
     $delete_permission = ($account->hasPermission("delete {$type} revisions") || $account->hasPermission('delete all revisions') || $account->hasPermission('administer support tickets')) && $support_ticket->access('delete');
     $rows = array();
     $vids = $support_ticket_storage->revisionIds($support_ticket);
     foreach (array_reverse($vids) as $vid) {
         $revision = $support_ticket_storage->loadRevision($vid);
         $username = ['#theme' => 'username', '#account' => $revision->uid->entity];
         // Use revision link to link to revisions that are not active.
         $date = $this->dateFormatter->format($revision->revision_timestamp->value, 'short');
         if ($vid != $support_ticket->getRevisionId()) {
             $link = $this->l($date, new Url('entity.support_ticket.revision', ['support_ticket' => $support_ticket->id(), 'support_ticket_revision' => $vid]));
         } else {
             $link = $support_ticket->link($date);
         }
         $row = [];
         $column = ['data' => ['#type' => 'inline_template', '#template' => '{% trans %}{{ date }} by {{ username }}{% endtrans %}{% if message %}<p class="revision-log">{{ message }}</p>{% endif %}', '#context' => ['date' => $link, 'username' => $this->renderer->renderPlain($username), 'message' => ['#markup' => $revision->revision_log->value]]]];
         // @todo Simplify once https://www.drupal.org/node/2334319 lands.
         $this->renderer->addCacheableDependency($column['data'], $username);
         $row[] = $column;
         if ($vid == $support_ticket->getRevisionId()) {
             $row[0]['class'] = ['revision-current'];
             $row[] = ['data' => ['#prefix' => '<em>', '#markup' => $this->t('current revision'), '#suffix' => '</em>'], 'class' => ['revision-current']];
         } else {
             $links = [];
             if ($revert_permission) {
                 $links['revert'] = ['title' => $this->t('Revert'), 'url' => Url::fromRoute('support_ticket.revision_revert_confirm', ['support_ticket' => $support_ticket->id(), 'support_ticket_revision' => $vid])];
             }
             if ($delete_permission) {
                 $links['delete'] = ['title' => $this->t('Delete'), 'url' => Url::fromRoute('support_ticket.revision_delete_confirm', ['support_ticket' => $support_ticket->id(), 'support_ticket_revision' => $vid])];
             }
             $row[] = ['data' => ['#type' => 'operations', '#links' => $links]];
         }
         $rows[] = $row;
     }
     $build['support_ticket_revisions_table'] = array('#theme' => 'table', '#rows' => $rows, '#header' => $header, '#attached' => array('library' => array('support_ticket/drupal.support_ticket.admin')));
     return $build;
 }
 /**
  * Returns a table which shows the differences between two support ticket revisions.
  *
  * @param SupportTicketInterface $support_ticket
  *   The support ticket whose revisions are compared.
  * @param $left_vid
  *   Vid of the support ticket revision from the left.
  * @param $right_vid
  *   Vid of the support ticket revision from the right.
  * @param $filter
  *   If $filter == 'raw' raw text is compared (including html tags)
  *   If filter == 'raw-plain' markdown function is applied to the text before comparison.
  *
  * @return array
  *   Table showing the diff between the two support ticket revisions.
  */
 public function compareSupportTicketRevisions(SupportTicketInterface $support_ticket, $left_vid, $right_vid, $filter)
 {
     $diff_rows = array();
     $build = array('#title' => $this->t('Revisions for %title', array('%title' => $support_ticket->label())));
     if (!in_array($filter, array('raw', 'raw-plain'))) {
         $filter = 'raw';
     } elseif ($filter == 'raw-plain') {
         $filter = 'raw_plain';
     }
     // Support Ticket storage service.
     $storage = $this->entityManager()->getStorage('support_ticket');
     $left_revision = $storage->loadRevision($left_vid);
     $right_revision = $storage->loadRevision($right_vid);
     $vids = $storage->revisionIds($support_ticket);
     $diff_rows[] = $this->buildRevisionsNavigation($support_ticket->id(), $vids, $left_vid, $right_vid);
     $diff_rows[] = $this->buildMarkdownNavigation($support_ticket->id(), $left_vid, $right_vid, $filter);
     $diff_header = $this->buildTableHeader($left_revision, $right_revision);
     // Perform comparison only if both support ticket revisions loaded successfully.
     if ($left_revision != FALSE && $right_revision != FALSE) {
         $fields = $this->compareRevisions($left_revision, $right_revision);
         $support_ticket_base_fields = $this->entityManager()->getBaseFieldDefinitions('support_ticket');
         // Check to see if we need to display certain fields or not based on
         // selected view mode display settings.
         foreach ($fields as $field_name => $field) {
             // If we are dealing with support tickets only compare those fields
             // set as visible from the selected view mode.
             $view_mode = $this->config->get('support_ticket_type_settings.' . $support_ticket->getType() . '.view_mode');
             // If no view mode is selected use the default view mode.
             if ($view_mode == NULL) {
                 $view_mode = 'default';
             }
             $visible = entity_get_display('support_ticket', $support_ticket->getType(), $view_mode)->getComponent($field_name);
             if ($visible == NULL && !array_key_exists($field_name, $support_ticket_base_fields)) {
                 unset($fields[$field_name]);
             }
         }
         // Build the diff rows for each field and append the field rows
         // to the table rows.
         foreach ($fields as $field) {
             $field_label_row = '';
             if (!empty($field['#name'])) {
                 $field_label_row = array('data' => $this->t('Changes to %name', array('%name' => $field['#name'])), 'colspan' => 4, 'class' => array('field-name'));
             }
             $field_diff_rows = $this->getRows($field['#states'][$filter]['#left'], $field['#states'][$filter]['#right']);
             // Add the field label to the table only if there are changes to that field.
             if (!empty($field_diff_rows) && !empty($field_label_row)) {
                 $diff_rows[] = array($field_label_row);
             }
             // Add field diff rows to the table rows.
             $diff_rows = array_merge($diff_rows, $field_diff_rows);
         }
         // Add the CSS for the diff.
         $build['#attached']['library'][] = 'diff/diff.general';
         $theme = $this->config->get('general_settings.theme');
         if ($theme) {
             if ($theme == 'default') {
                 $build['#attached']['library'][] = 'diff/diff.default';
             } elseif ($theme == 'github') {
                 $build['#attached']['library'][] = 'diff/diff.github';
             }
         } elseif ($theme == NULL) {
             $build['#attached']['library'][] = 'diff/diff.github';
         }
         $build['diff'] = array('#type' => 'table', '#header' => $diff_header, '#rows' => $diff_rows, '#empty' => $this->t('No visible changes'), '#attributes' => array('class' => array('diff')));
         $build['back'] = array('#type' => 'link', '#attributes' => array('class' => array('button', 'diff-button')), '#title' => $this->t('Back to Revision Overview'), '#url' => Url::fromRoute('entity.support_ticket.version_history', ['support_ticket' => $support_ticket->id()]));
         return $build;
     } else {
         // @todo When task 'Convert drupal_set_message() to a service' (2278383)
         //   will be merged use the corresponding service instead.
         drupal_set_message($this->t('Selected support ticket revisions could not be loaded.'), 'error');
     }
 }