PageRenderTime 27ms CodeModel.GetById 22ms RepoModel.GetById 0ms app.codeStats 0ms

/core/modules/views/src/Plugin/views/display/Feed.php

https://gitlab.com/geeta7/drupal
PHP | 315 lines | 185 code | 47 blank | 83 comment | 18 complexity | 3d007588513e08c6593b9fd33459121b MD5 | raw file
  1. <?php
  2. /**
  3. * @file
  4. * Contains \Drupal\views\Plugin\views\display\Feed.
  5. */
  6. namespace Drupal\views\Plugin\views\display;
  7. use Drupal\Core\Cache\CacheableMetadata;
  8. use Drupal\Core\Cache\CacheableResponse;
  9. use Drupal\Core\Form\FormStateInterface;
  10. use Drupal\views\ViewExecutable;
  11. use Drupal\views\Views;
  12. use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
  13. /**
  14. * The plugin that handles a feed, such as RSS or atom.
  15. *
  16. * @ingroup views_display_plugins
  17. *
  18. * @ViewsDisplay(
  19. * id = "feed",
  20. * title = @Translation("Feed"),
  21. * help = @Translation("Display the view as a feed, such as an RSS feed."),
  22. * uses_route = TRUE,
  23. * admin = @Translation("Feed"),
  24. * returns_response = TRUE
  25. * )
  26. */
  27. class Feed extends PathPluginBase implements ResponseDisplayPluginInterface {
  28. /**
  29. * Whether the display allows the use of AJAX or not.
  30. *
  31. * @var bool
  32. */
  33. protected $ajaxEnabled = FALSE;
  34. /**
  35. * Whether the display allows the use of a pager or not.
  36. *
  37. * @var bool
  38. */
  39. protected $usesPager = FALSE;
  40. /**
  41. * {@inheritdoc}
  42. */
  43. public function getType() {
  44. return 'feed';
  45. }
  46. /**
  47. * {@inheritdoc}
  48. */
  49. public static function buildResponse($view_id, $display_id, array $args = []) {
  50. $build = static::buildBasicRenderable($view_id, $display_id, $args);
  51. // Set up an empty response, so for example RSS can set the proper
  52. // Content-Type header.
  53. $response = new CacheableResponse('', 200);
  54. $build['#response'] = $response;
  55. /** @var \Drupal\Core\Render\RendererInterface $renderer */
  56. $renderer = \Drupal::service('renderer');
  57. $output = (string) $renderer->renderRoot($build);
  58. if (empty($output)) {
  59. throw new NotFoundHttpException();
  60. }
  61. $response->setContent($output);
  62. $cache_metadata = CacheableMetadata::createFromRenderArray($build);
  63. $response->addCacheableDependency($cache_metadata);
  64. return $response;
  65. }
  66. /**
  67. * {@inheritdoc}
  68. */
  69. public function execute() {
  70. parent::execute();
  71. return $this->view->render();
  72. }
  73. /**
  74. * {@inheritdoc}
  75. */
  76. public function preview() {
  77. $output = $this->view->render();
  78. if (!empty($this->view->live_preview)) {
  79. $output = array(
  80. '#prefix' => '<pre>',
  81. '#plain_text' => drupal_render_root($output),
  82. '#suffix' => '</pre>',
  83. );
  84. }
  85. return $output;
  86. }
  87. /**
  88. * {@inheritdoc}
  89. */
  90. public function render() {
  91. $build = $this->view->style_plugin->render($this->view->result);
  92. $this->applyDisplayCachablityMetadata($build);
  93. return $build;
  94. }
  95. /**
  96. * {@inheritdoc}
  97. */
  98. public function defaultableSections($section = NULL) {
  99. $sections = parent::defaultableSections($section);
  100. if (in_array($section, array('style', 'row'))) {
  101. return FALSE;
  102. }
  103. // Tell views our sitename_title option belongs in the title section.
  104. if ($section == 'title') {
  105. $sections[] = 'sitename_title';
  106. }
  107. elseif (!$section) {
  108. $sections['title'][] = 'sitename_title';
  109. }
  110. return $sections;
  111. }
  112. /**
  113. * {@inheritdoc}
  114. */
  115. protected function defineOptions() {
  116. $options = parent::defineOptions();
  117. $options['displays'] = array('default' => array());
  118. // Overrides for standard stuff.
  119. $options['style']['contains']['type']['default'] = 'rss';
  120. $options['style']['contains']['options']['default'] = array('description' => '');
  121. $options['sitename_title']['default'] = FALSE;
  122. $options['row']['contains']['type']['default'] = 'rss_fields';
  123. $options['defaults']['default']['style'] = FALSE;
  124. $options['defaults']['default']['row'] = FALSE;
  125. return $options;
  126. }
  127. /**
  128. * {@inheritdoc}
  129. */
  130. public function newDisplay() {
  131. parent::newDisplay();
  132. // Set the default row style. Ideally this would be part of the option
  133. // definition, but in this case it's dependent on the view's base table,
  134. // which we don't know until init().
  135. if (empty($this->options['row']['type']) || $this->options['row']['type'] === 'rss_fields') {
  136. $row_plugins = Views::fetchPluginNames('row', $this->getType(), array($this->view->storage->get('base_table')));
  137. $default_row_plugin = key($row_plugins);
  138. $options = $this->getOption('row');
  139. $options['type'] = $default_row_plugin;
  140. $this->setOption('row', $options);
  141. }
  142. }
  143. /**
  144. * {@inheritdoc}
  145. */
  146. public function optionsSummary(&$categories, &$options) {
  147. parent::optionsSummary($categories, $options);
  148. // Since we're childing off the 'path' type, we'll still *call* our
  149. // category 'page' but let's override it so it says feed settings.
  150. $categories['page'] = array(
  151. 'title' => $this->t('Feed settings'),
  152. 'column' => 'second',
  153. 'build' => array(
  154. '#weight' => -10,
  155. ),
  156. );
  157. if ($this->getOption('sitename_title')) {
  158. $options['title']['value'] = $this->t('Using the site name');
  159. }
  160. $displays = array_filter($this->getOption('displays'));
  161. if (count($displays) > 1) {
  162. $attach_to = $this->t('Multiple displays');
  163. }
  164. elseif (count($displays) == 1) {
  165. $display = array_shift($displays);
  166. $displays = $this->view->storage->get('display');
  167. if (!empty($displays[$display])) {
  168. $attach_to = $displays[$display]['display_title'];
  169. }
  170. }
  171. if (!isset($attach_to)) {
  172. $attach_to = $this->t('None');
  173. }
  174. $options['displays'] = array(
  175. 'category' => 'page',
  176. 'title' => $this->t('Attach to'),
  177. 'value' => $attach_to,
  178. );
  179. }
  180. /**
  181. * {@inheritdoc}
  182. */
  183. public function buildOptionsForm(&$form, FormStateInterface $form_state) {
  184. // It is very important to call the parent function here.
  185. parent::buildOptionsForm($form, $form_state);
  186. switch ($form_state->get('section')) {
  187. case 'title':
  188. $title = $form['title'];
  189. // A little juggling to move the 'title' field beyond our checkbox.
  190. unset($form['title']);
  191. $form['sitename_title'] = array(
  192. '#type' => 'checkbox',
  193. '#title' => $this->t('Use the site name for the title'),
  194. '#default_value' => $this->getOption('sitename_title'),
  195. );
  196. $form['title'] = $title;
  197. $form['title']['#states'] = array(
  198. 'visible' => array(
  199. ':input[name="sitename_title"]' => array('checked' => FALSE),
  200. ),
  201. );
  202. break;
  203. case 'displays':
  204. $form['#title'] .= $this->t('Attach to');
  205. $displays = array();
  206. foreach ($this->view->storage->get('display') as $display_id => $display) {
  207. // @todo The display plugin should have display_title and id as well.
  208. if ($this->view->displayHandlers->has($display_id) && $this->view->displayHandlers->get($display_id)->acceptAttachments()) {
  209. $displays[$display_id] = $display['display_title'];
  210. }
  211. }
  212. $form['displays'] = array(
  213. '#title' => $this->t('Displays'),
  214. '#type' => 'checkboxes',
  215. '#description' => $this->t('The feed icon will be available only to the selected displays.'),
  216. '#options' => array_map('\Drupal\Component\Utility\Html::escape', $displays),
  217. '#default_value' => $this->getOption('displays'),
  218. );
  219. break;
  220. case 'path':
  221. $form['path']['#description'] = $this->t('This view will be displayed by visiting this path on your site. It is recommended that the path be something like "path/%/%/feed" or "path/%/%/rss.xml", putting one % in the path for each contextual filter you have defined in the view.');
  222. }
  223. }
  224. /**
  225. * {@inheritdoc}
  226. */
  227. public function submitOptionsForm(&$form, FormStateInterface $form_state) {
  228. parent::submitOptionsForm($form, $form_state);
  229. $section = $form_state->get('section');
  230. switch ($section) {
  231. case 'title':
  232. $this->setOption('sitename_title', $form_state->getValue('sitename_title'));
  233. break;
  234. case 'displays':
  235. $this->setOption($section, $form_state->getValue($section));
  236. break;
  237. }
  238. }
  239. /**
  240. * {@inheritdoc}
  241. */
  242. public function attachTo(ViewExecutable $clone, $display_id, array &$build) {
  243. $displays = $this->getOption('displays');
  244. if (empty($displays[$display_id])) {
  245. return;
  246. }
  247. // Defer to the feed style; it may put in meta information, and/or
  248. // attach a feed icon.
  249. $clone->setArguments($this->view->args);
  250. $clone->setDisplay($this->display['id']);
  251. $clone->buildTitle();
  252. if ($plugin = $clone->display_handler->getPlugin('style')) {
  253. $plugin->attachTo($build, $display_id, $clone->getUrl(), $clone->getTitle());
  254. foreach ($clone->feedIcons as $feed_icon) {
  255. $this->view->feedIcons[] = $feed_icon;
  256. }
  257. }
  258. // Clean up.
  259. $clone->destroy();
  260. unset($clone);
  261. }
  262. /**
  263. * {@inheritdoc}
  264. */
  265. public function usesLinkDisplay() {
  266. return TRUE;
  267. }
  268. }