PageRenderTime 66ms CodeModel.GetById 11ms RepoModel.GetById 1ms app.codeStats 0ms

/src/Form/RevisionOverviewForm.php

https://gitlab.com/Drulenium-bot/diff
PHP | 356 lines | 246 code | 34 blank | 76 comment | 19 complexity | 3ead1ccd126e2021a64814e49a731f5a MD5 | raw file
  1. <?php
  2. namespace Drupal\diff\Form;
  3. use Drupal\Core\Language\LanguageManagerInterface;
  4. use Symfony\Component\DependencyInjection\ContainerInterface;
  5. use Drupal\Core\Entity\EntityManagerInterface;
  6. use Drupal\Core\Form\FormBase;
  7. use Drupal\Component\Utility\Xss;
  8. use Drupal\Core\Session\AccountInterface;
  9. use Drupal\Core\Datetime\DateFormatter;
  10. use Drupal\Core\Form\FormStateInterface;
  11. use Drupal\Core\Url;
  12. use Drupal\Core\Render\RendererInterface;
  13. /**
  14. * Provides a form for revision overview page.
  15. */
  16. class RevisionOverviewForm extends FormBase {
  17. /**
  18. * The entity manager.
  19. *
  20. * @var \Drupal\Core\Entity\EntityManagerInterface
  21. */
  22. protected $entityManager;
  23. /**
  24. * The current user service.
  25. *
  26. * @var \Drupal\Core\Session\AccountInterface
  27. */
  28. protected $currentUser;
  29. /**
  30. * The date service.
  31. *
  32. * @var \Drupal\Core\Datetime\DateFormatter
  33. */
  34. protected $date;
  35. /**
  36. * The renderer service.
  37. *
  38. * @var \Drupal\Core\Render\RendererInterface
  39. */
  40. protected $renderer;
  41. /**
  42. * The language manager.
  43. *
  44. * @var \Drupal\Core\Language\LanguageManagerInterface $language_manager
  45. */
  46. protected $languageManager;
  47. /**
  48. * Wrapper object for writing/reading simple configuration from diff.settings.yml
  49. */
  50. protected $config;
  51. /**
  52. * Constructs a RevisionOverviewForm object.
  53. *
  54. * @param \Drupal\Core\Entity\EntityManagerInterface $entityManager
  55. * The entity manager.
  56. * @param \Drupal\Core\Session\AccountInterface $currentUser
  57. * The current user.
  58. * @param \Drupal\Core\Datetime\DateFormatter $date
  59. * The date service.
  60. * @param \Drupal\Core\Render\RendererInterface
  61. * The renderer service.
  62. * @param \Drupal\Core\Language\LanguageManagerInterface $language_manager
  63. * The language manager.
  64. */
  65. public function __construct(EntityManagerInterface $entityManager, AccountInterface $currentUser, DateFormatter $date, RendererInterface $renderer, LanguageManagerInterface $language_manager) {
  66. $this->entityManager = $entityManager;
  67. $this->currentUser = $currentUser;
  68. $this->date = $date;
  69. $this->renderer = $renderer;
  70. $this->languageManager = $language_manager;
  71. $this->config = $this->config('diff.settings');
  72. }
  73. /**
  74. * {@inheritdoc}
  75. */
  76. public static function create(ContainerInterface $container) {
  77. return new static(
  78. $container->get('entity.manager'),
  79. $container->get('current_user'),
  80. $container->get('date.formatter'),
  81. $container->get('renderer'),
  82. $container->get('language_manager')
  83. );
  84. }
  85. /**
  86. * {@inheritdoc}
  87. */
  88. public function getFormId() {
  89. return 'revision_overview_form';
  90. }
  91. /**
  92. * {@inheritdoc}
  93. */
  94. public function buildForm(array $form, FormStateInterface $form_state, $node = NULL) {
  95. $account = $this->currentUser;
  96. $langcode = $node->language()->getId();
  97. $langname = $node->language()->getName();
  98. $languages = $node->getTranslationLanguages();
  99. $has_translations = (count($languages) > 1);
  100. $node_storage = $this->entityManager->getStorage('node');
  101. $type = $node->getType();
  102. $pagerLimit = $this->config->get('general_settings.revision_pager_limit');
  103. $query = \Drupal::entityQuery('node')
  104. ->condition($node->getEntityType()->getKey('id'), $node->id())
  105. ->pager($pagerLimit)
  106. ->allRevisions()
  107. ->sort($node->getEntityType()->getKey('revision'), 'DESC')
  108. ->execute();
  109. $vids = array_keys($query);
  110. $revision_count = count($vids);
  111. $build['#title'] = $has_translations ? $this->t('@langname revisions for %title', ['@langname' => $langname, '%title' => $node->label()]) : $this->t('Revisions for %title', ['%title' => $node->label()]);
  112. $build['nid'] = array(
  113. '#type' => 'hidden',
  114. '#value' => $node->id(),
  115. );
  116. $table_header = array(
  117. 'revision' => $this->t('Revision'),
  118. 'operations' => $this->t('Operations'),
  119. );
  120. // Allow comparisons only if there are 2 or more revisions.
  121. if ($revision_count > 1) {
  122. $table_header += array(
  123. 'select_column_one' => '',
  124. 'select_column_two' => '',
  125. );
  126. }
  127. $rev_revert_perm = $account->hasPermission("revert $type revisions") ||
  128. $account->hasPermission('revert all revisions') ||
  129. $account->hasPermission('administer nodes');
  130. $rev_delete_perm = $account->hasPermission("delete $type revisions") ||
  131. $account->hasPermission('delete all revisions') ||
  132. $account->hasPermission('administer nodes');
  133. $revert_permission = $rev_revert_perm && $node->access('update');
  134. $delete_permission = $rev_delete_perm && $node->access('delete');
  135. // Contains the table listing the revisions.
  136. $build['node_revisions_table'] = array(
  137. '#type' => 'table',
  138. '#header' => $table_header,
  139. '#attributes' => array('class' => array('diff-revisions')),
  140. );
  141. $build['node_revisions_table']['#attached']['library'][] = 'diff/diff.general';
  142. $build['node_revisions_table']['#attached']['drupalSettings']['diffRevisionRadios'] = $this->config->get('general_settings.radio_behavior');
  143. $page = \Drupal::request()->query->get('page');
  144. $latest_revision = empty($page);
  145. // Add rows to the table.
  146. foreach ($vids as $vid) {
  147. if ($revision = $node_storage->loadRevision($vid)) {
  148. if ($revision->hasTranslation($langcode) && $revision->getTranslation($langcode)->isRevisionTranslationAffected()) {
  149. $username = array(
  150. '#theme' => 'username',
  151. '#account' => $revision->getRevisionAuthor(),
  152. );
  153. $revision_date = $this->date->format($revision->getRevisionCreationTime(), 'short');
  154. // Use revision link to link to revisions that are not active.
  155. if ($vid != $node->getRevisionId()) {
  156. $link = $this->l($revision_date, new Url('entity.node.revision', ['node' => $node->id(), 'node_revision' => $vid]));
  157. }
  158. else {
  159. $link = $node->link($revision_date);
  160. }
  161. // Default revision.
  162. if ($latest_revision) {
  163. $row = array(
  164. 'revision' => array(
  165. '#type' => 'inline_template',
  166. '#template' => '{% trans %}{{ date }} by {{ username }}{% endtrans %}{% if message %}<p class="revision-log">{{ message }}</p>{% endif %}',
  167. '#context' => [
  168. 'date' => $link,
  169. 'username' => $this->renderer->renderPlain($username),
  170. 'message' => ['#markup' => $revision->revision_log->value, '#allowed_tags' => Xss::getHtmlTagList()],
  171. ],
  172. ),
  173. );
  174. // Allow comparisons only if there are 2 or more revisions.
  175. if ($revision_count > 1) {
  176. $row += array(
  177. 'select_column_one' => array(
  178. '#type' => 'radio',
  179. '#title_display' => 'invisible',
  180. '#name' => 'radios_left',
  181. '#return_value' => $vid,
  182. '#default_value' => FALSE,
  183. ),
  184. 'select_column_two' => array(
  185. '#type' => 'radio',
  186. '#title_display' => 'invisible',
  187. '#name' => 'radios_right',
  188. '#default_value' => $vid,
  189. '#return_value' => $vid,
  190. ),
  191. );
  192. }
  193. $row['operations'] = array(
  194. '#prefix' => '<em>',
  195. '#markup' => $this->t('Current revision'),
  196. '#suffix' => '</em>',
  197. '#attributes' => array(
  198. 'class' => array('revision-current'),
  199. )
  200. );
  201. $latest_revision = FALSE;
  202. }
  203. else {
  204. $route_params = array(
  205. 'node' => $node->id(),
  206. 'node_revision' => $vid,
  207. 'langcode' => $langcode,
  208. );
  209. $links = array();
  210. if ($revert_permission) {
  211. $links['revert'] = [
  212. 'title' => $this->t('Revert'),
  213. 'url' => $has_translations ?
  214. Url::fromRoute('node.revision_revert_translation_confirm', ['node' => $node->id(), 'node_revision' => $vid, 'langcode' => $langcode]) :
  215. Url::fromRoute('node.revision_revert_confirm', ['node' => $node->id(), 'node_revision' => $vid]),
  216. ];
  217. }
  218. if ($delete_permission) {
  219. $links['delete'] = array(
  220. 'title' => $this->t('Delete'),
  221. 'url' => Url::fromRoute('node.revision_delete_confirm', $route_params)
  222. );
  223. }
  224. // Here we don't have to deal with 'only one revision' case because
  225. // if there's only one revision it will also be the default one,
  226. // entering on the first branch of this if else statement.
  227. $row = array(
  228. 'revision' => array(
  229. '#type' => 'inline_template',
  230. '#template' => '{% trans %}{{ date }} by {{ username }}{% endtrans %}{% if message %}<p class="revision-log">{{ message }}</p>{% endif %}',
  231. '#context' => [
  232. 'date' => $link,
  233. 'username' => $this->renderer->renderPlain($username),
  234. 'message' => ['#markup' => $revision->revision_log->value, '#allowed_tags' => Xss::getHtmlTagList()],
  235. ],
  236. ),
  237. 'select_column_one' => array(
  238. '#type' => 'radio',
  239. '#title_display' => 'invisible',
  240. '#name' => 'radios_left',
  241. '#return_value' => $vid,
  242. '#default_value' => isset ($vids[1]) ? $vids[1] : FALSE,
  243. ),
  244. 'select_column_two' => array(
  245. '#type' => 'radio',
  246. '#title_display' => 'invisible',
  247. '#name' => 'radios_right',
  248. '#return_value' => $vid,
  249. '#default_value' => FALSE,
  250. ),
  251. 'operations' => array(
  252. '#type' => 'operations',
  253. '#links' => $links,
  254. ),
  255. );
  256. }
  257. // Add the row to the table.
  258. $build['node_revisions_table'][] = $row;
  259. }
  260. }
  261. }
  262. // Allow comparisons only if there are 2 or more revisions.
  263. if ($revision_count > 1) {
  264. $build['submit'] = array(
  265. '#type' => 'submit',
  266. '#value' => t('Compare'),
  267. '#attributes' => array(
  268. 'class' => array(
  269. 'diff-button',
  270. ),
  271. ),
  272. );
  273. }
  274. $build['pager'] = array(
  275. '#type' => 'pager',
  276. );
  277. return $build;
  278. }
  279. /**
  280. * {@inheritdoc}
  281. */
  282. public function validateForm(array &$form, FormStateInterface $form_state) {
  283. $input = $form_state->getUserInput();
  284. if (count($form_state->getValue('node_revisions_table')) <= 1) {
  285. $form_state->setErrorByName('node_revisions_table', $this->t('Multiple revisions are needed for comparison.'));
  286. }
  287. elseif (!isset($input['radios_left']) || !isset($input['radios_right'])) {
  288. $form_state->setErrorByName('node_revisions_table', $this->t('Select two revisions to compare.'));
  289. }
  290. elseif ($input['radios_left'] == $input['radios_right']) {
  291. // @todo Radio-boxes selection resets if there are errors.
  292. $form_state->setErrorByName('node_revisions_table', $this->t('Select different revisions to compare.'));
  293. }
  294. }
  295. /**
  296. * {@inheritdoc}
  297. */
  298. public function submitForm(array &$form, FormStateInterface $form_state) {
  299. $input = $form_state->getUserInput();
  300. $vid_left = $input['radios_left'];
  301. $vid_right = $input['radios_right'];
  302. $nid = $input['nid'];
  303. // Always place the older revision on the left side of the comparison
  304. // and the newer revision on the right side (however revisions can be
  305. // compared both ways if we manually change the order of the parameters).
  306. if ($vid_left > $vid_right) {
  307. $aux = $vid_left;
  308. $vid_left = $vid_right;
  309. $vid_right = $aux;
  310. }
  311. // Builds the redirect Url.
  312. $redirect_url = Url::fromRoute(
  313. 'diff.revisions_diff',
  314. array(
  315. 'node' => $nid,
  316. 'left_revision' => $vid_left,
  317. 'right_revision' => $vid_right,
  318. )
  319. );
  320. $form_state->setRedirectUrl($redirect_url);
  321. }
  322. }