3 namespace Drupal\views\Plugin\views\row;
5 use Drupal\Core\Form\FormStateInterface;
9 * Renders an RSS item based on fields.
13 * title = @Translation("Fields"),
14 * help = @Translation("Display fields as RSS items."),
15 * theme = "views_view_row_rss",
16 * display_types = {"feed"}
19 class RssFields extends RowPluginBase {
22 * Does the row plugin support to add fields to its output.
26 protected $usesFields = TRUE;
28 protected function defineOptions() {
29 $options = parent::defineOptions();
30 $options['title_field'] = ['default' => ''];
31 $options['link_field'] = ['default' => ''];
32 $options['description_field'] = ['default' => ''];
33 $options['creator_field'] = ['default' => ''];
34 $options['date_field'] = ['default' => ''];
35 $options['guid_field_options']['contains']['guid_field'] = ['default' => ''];
36 $options['guid_field_options']['contains']['guid_field_is_permalink'] = ['default' => TRUE];
40 public function buildOptionsForm(&$form, FormStateInterface $form_state) {
41 parent::buildOptionsForm($form, $form_state);
43 $initial_labels = ['' => $this->t('- None -')];
44 $view_fields_labels = $this->displayHandler->getFieldLabels();
45 $view_fields_labels = array_merge($initial_labels, $view_fields_labels);
47 $form['title_field'] = [
49 '#title' => $this->t('Title field'),
50 '#description' => $this->t('The field that is going to be used as the RSS item title for each row.'),
51 '#options' => $view_fields_labels,
52 '#default_value' => $this->options['title_field'],
55 $form['link_field'] = [
57 '#title' => $this->t('Link field'),
58 '#description' => $this->t('The field that is going to be used as the RSS item link for each row. This must be a drupal relative path.'),
59 '#options' => $view_fields_labels,
60 '#default_value' => $this->options['link_field'],
63 $form['description_field'] = [
65 '#title' => $this->t('Description field'),
66 '#description' => $this->t('The field that is going to be used as the RSS item description for each row.'),
67 '#options' => $view_fields_labels,
68 '#default_value' => $this->options['description_field'],
71 $form['creator_field'] = [
73 '#title' => $this->t('Creator field'),
74 '#description' => $this->t('The field that is going to be used as the RSS item creator for each row.'),
75 '#options' => $view_fields_labels,
76 '#default_value' => $this->options['creator_field'],
79 $form['date_field'] = [
81 '#title' => $this->t('Publication date field'),
82 '#description' => $this->t('The field that is going to be used as the RSS item pubDate for each row. It needs to be in RFC 2822 format.'),
83 '#options' => $view_fields_labels,
84 '#default_value' => $this->options['date_field'],
87 $form['guid_field_options'] = [
89 '#title' => $this->t('GUID settings'),
92 $form['guid_field_options']['guid_field'] = [
94 '#title' => $this->t('GUID field'),
95 '#description' => $this->t('The globally unique identifier of the RSS item.'),
96 '#options' => $view_fields_labels,
97 '#default_value' => $this->options['guid_field_options']['guid_field'],
100 $form['guid_field_options']['guid_field_is_permalink'] = [
101 '#type' => 'checkbox',
102 '#title' => $this->t('GUID is permalink'),
103 '#description' => $this->t('The RSS item GUID is a permalink.'),
104 '#default_value' => $this->options['guid_field_options']['guid_field_is_permalink'],
108 public function validate() {
109 $errors = parent::validate();
110 $required_options = ['title_field', 'link_field', 'description_field', 'creator_field', 'date_field'];
111 foreach ($required_options as $required_option) {
112 if (empty($this->options[$required_option])) {
113 $errors[] = $this->t('Row style plugin requires specifying which views fields to use for RSS item.');
117 // Once more for guid.
118 if (empty($this->options['guid_field_options']['guid_field'])) {
119 $errors[] = $this->t('Row style plugin requires specifying which views fields to use for RSS item.');
124 public function render($row) {
126 if (!isset($row_index)) {
129 if (function_exists('rdf_get_namespaces')) {
130 // Merge RDF namespaces in the XML namespaces in case they are used
131 // further in the RSS content.
132 $xml_rdf_namespaces = [];
133 foreach (rdf_get_namespaces() as $prefix => $uri) {
134 $xml_rdf_namespaces['xmlns:' . $prefix] = $uri;
136 $this->view->style_plugin->namespaces += $xml_rdf_namespaces;
139 // Create the RSS item object.
140 $item = new \stdClass();
141 $item->title = $this->getField($row_index, $this->options['title_field']);
142 // @todo Views should expect and store a leading /. See:
143 // https://www.drupal.org/node/2423913
144 $item->link = Url::fromUserInput('/' . $this->getField($row_index, $this->options['link_field']))->setAbsolute()->toString();
146 $field = $this->getField($row_index, $this->options['description_field']);
147 $item->description = is_array($field) ? $field : ['#markup' => $field];
150 ['key' => 'pubDate', 'value' => $this->getField($row_index, $this->options['date_field'])],
152 'key' => 'dc:creator',
153 'value' => $this->getField($row_index, $this->options['creator_field']),
154 'namespace' => ['xmlns:dc' => 'http://purl.org/dc/elements/1.1/'],
157 $guid_is_permalink_string = 'false';
158 $item_guid = $this->getField($row_index, $this->options['guid_field_options']['guid_field']);
159 if ($this->options['guid_field_options']['guid_field_is_permalink']) {
160 $guid_is_permalink_string = 'true';
161 // @todo Enforce GUIDs as system-generated rather than user input? See
162 // https://www.drupal.org/node/2430589.
163 $item_guid = Url::fromUserInput('/' . $item_guid)->setAbsolute()->toString();
165 $item->elements[] = [
167 'value' => $item_guid,
168 'attributes' => ['isPermaLink' => $guid_is_permalink_string],
173 foreach ($item->elements as $element) {
174 if (isset($element['namespace'])) {
175 $this->view->style_plugin->namespaces = array_merge($this->view->style_plugin->namespaces, $element['namespace']);
180 '#theme' => $this->themeFunctions(),
181 '#view' => $this->view,
182 '#options' => $this->options,
184 '#field_alias' => isset($this->field_alias) ? $this->field_alias : '',
191 * Retrieves a views field value from the style plugin.
194 * The index count of the row as expected by views_plugin_style::getField().
196 * The ID assigned to the required field in the display.
198 * @return string|null|\Drupal\Component\Render\MarkupInterface
199 * An empty string if there is no style plugin, or the field ID is empty.
200 * NULL if the field value is empty. If neither of these conditions apply,
201 * a MarkupInterface object containing the rendered field value.
203 public function getField($index, $field_id) {
204 if (empty($this->view->style_plugin) || !is_object($this->view->style_plugin) || empty($field_id)) {
207 return $this->view->style_plugin->getField($index, $field_id);