class RssFields in Views RSS 8.2
Same name in this branch
- 8.2 src/Plugin/views/style/RssFields.php \Drupal\views_rss\Plugin\views\style\RssFields
- 8.2 src/Plugin/views/row/RssFields.php \Drupal\views_rss\Plugin\views\row\RssFields
Same name and namespace in other branches
- 8.3 src/Plugin/views/row/RssFields.php \Drupal\views_rss\Plugin\views\row\RssFields
Renders an RSS item based on fields.
Plugin annotation
@ViewsRow(
id = "views_rss_fields",
title = @Translation("RSS Feed - Fields"),
help = @Translation("Display fields as RSS items."),
theme = "views_view_row_rss",
display_types = {"feed"}
)
Hierarchy
- class \Drupal\Component\Plugin\PluginBase implements DerivativeInspectionInterface, PluginInspectionInterface
- class \Drupal\Core\Plugin\PluginBase uses DependencySerializationTrait, MessengerTrait, StringTranslationTrait
- class \Drupal\views\Plugin\views\PluginBase implements DependentPluginInterface, ContainerFactoryPluginInterface, TrustedCallbackInterface, ViewsPluginInterface
- class \Drupal\views\Plugin\views\row\RowPluginBase
- class \Drupal\views_rss\Plugin\views\row\RssFields
- class \Drupal\views\Plugin\views\row\RowPluginBase
- class \Drupal\views\Plugin\views\PluginBase implements DependentPluginInterface, ContainerFactoryPluginInterface, TrustedCallbackInterface, ViewsPluginInterface
- class \Drupal\Core\Plugin\PluginBase uses DependencySerializationTrait, MessengerTrait, StringTranslationTrait
Expanded class hierarchy of RssFields
File
- src/
Plugin/ views/ row/ RssFields.php, line 22
Namespace
Drupal\views_rss\Plugin\views\rowView source
class RssFields extends RowPluginBase {
/**
* Does the row plugin support to add fields to it's output.
*
* @var bool
*/
protected $usesFields = TRUE;
/**
* Function defineOptions.
*/
protected function defineOptions() {
$options = parent::defineOptions();
$item_elements = views_rss_get('item_elements');
if (count($item_elements)) {
foreach ($item_elements as $module => $module_item_elements) {
foreach (array_keys($module_item_elements) as $element) {
list($namespace, $element_name) = views_rss_extract_element_names($element, 'core');
$options['item']['contains'][$namespace]['contains'][$module]['contains'][$element_name] = [
'default' => NULL,
];
}
}
}
return $options;
}
/**
* Function buildOptionsForm.
*/
public function buildOptionsForm(&$form, FormStateInterface $form_state) {
parent::buildOptionsForm($form, $form_state);
$initial_labels = array(
'' => $this
->t('- None -'),
);
$view_fields_labels = $this->displayHandler
->getFieldLabels();
$view_fields_labels = array_merge($initial_labels, $view_fields_labels);
$item_elements = views_rss_get('item_elements');
if (count($item_elements)) {
foreach ($item_elements as $module => $module_item_elements) {
foreach ($module_item_elements as $element => $definition) {
if (!isset($definition['configurable']) || $definition['configurable']) {
list($namespace, $element_name) = views_rss_extract_element_names($element, 'core');
// Add fieldset for namespace if not yet added.
if (!isset($form['item'][$namespace])) {
$form['item'][$namespace] = array(
'#type' => 'details',
'#title' => t('Item elements : @namespace', array(
'@namespace' => $namespace,
)),
'#description' => t('Select fields containing relevant values for <item> elements in "@namespace" namespace. See <a href="@guide_url">Views RSS documentation</a> for more information.', array(
'@namespace' => $namespace,
'@guide_url' => Url::fromUri('http://drupal.org/node/1344136'),
)),
'#open' => FALSE,
);
}
// Prepare form element.
$default_value = NULL;
if (!empty($this->options['item'][$namespace][$module][$element_name])) {
$default_value = $this->options['item'][$namespace][$module][$element_name];
}
elseif (!empty($definition['group'])) {
$default_value = $this->options['item'][$namespace][$module][$definition['group']][$element_name];
}
$form_item = array(
'#type' => 'select',
'#title' => Xss::filter(isset($definition['title']) ? $definition['title'] : $element_name),
'#description' => Xss::filter(isset($definition['description']) ? $definition['description'] : NULL),
'#options' => $view_fields_labels,
'#default_value' => $default_value,
);
// Allow to overwrite default form element.
if (!empty($definition['settings form'])) {
$form_item = array_merge($form_item, $definition['settings form']);
// Make sure that #options is an associative array.
if (!empty($definition['settings form']['#options'])) {
$form_item['#options'] = views_rss_map_assoc($definition['settings form']['#options']);
}
}
// Add help link if provided.
if (isset($definition['help']) && $definition['help']) {
$form_item['#description'] .= ' ' . Link::fromTextAndUrl('[?]', Url::fromUri($definition['help']), array(
'attributes' => array(
'title' => t('Need more information?'),
),
))
->toString();
}
// Check if element should be displayed in a subgroup.
if (isset($definition['group']) && $definition['group']) {
// Add a subgroup to the form if it not yet added.
if (!isset($form['item'][$namespace][$module][$definition['group']])) {
// Does module provide the group definition?
$group_title = !empty($element_groups[$module][$definition['group']]['title']) ? $element_groups[$module][$definition['group']]['title'] : $definition['group'];
$group_description = !empty($element_groups[$module][$definition['group']]['description']) ? $element_groups[$module][$definition['group']]['description'] : NULL;
$form['item'][$namespace][$module][$definition['group']] = array(
'#type' => 'details',
'#title' => Xss::filter($group_title),
'#description' => Xss::filter($group_description),
'#open' => FALSE,
);
}
$form['item'][$namespace][$module][$definition['group']][$element_name] = $form_item;
}
else {
$form['item'][$namespace][$module][$element_name] = $form_item;
}
}
}
}
}
}
/**
* Validates whether views_rss_core module exists or not.
*/
public function validate() {
$errors = parent::validate();
if (!\Drupal::moduleHandler()
->moduleExists('views_rss_core')) {
$errors[] = $this
->t('You have to enable <em>Views RSS: Core Elements</em> module to have access to basic feed elements.');
}
else {
// An item MUST contain either a title or description.
// All other elements are optional according to RSS specification.
if (empty($this->options['item']['core']['views_rss_core']['title']) && empty($this->options['item']['core']['views_rss_core']['description'])) {
$errors[] = $this
->t('You have to configure either <em>title</em> or <em>description</em> core element.');
}
}
return $errors;
}
/**
* Protected fuction mapRow.
*/
protected function mapRow($row) {
$rendered_fields = $raw_fields = array();
$field_ids = array_keys($this->view->field);
if (!empty($field_ids)) {
foreach ($field_ids as $field_id) {
// Render the final field value.
$rendered_fields[$field_id] = $this
->getField($row->index, $field_id);
// Also let's keep raw value for further processing.
$raw_fields[$field_id] = array();
if (method_exists($this->view->field[$field_id], 'getItems')) {
$raw_fields[$field_id]['items'] = $this->view->field[$field_id]
->getItems($row);
}
}
}
// Rewrite view rows to XML item rows.
$item_elements = views_rss_get('item_elements');
foreach ($rendered_fields as $field_id => $rendered_field) {
$item = $raw_item = array();
foreach ($item_elements as $module => $module_item_elements) {
foreach ($module_item_elements as $element => $definition) {
list($namespace, $element_name) = views_rss_extract_element_names($element, 'core');
if (!empty($this->options['item'][$namespace][$module][$element_name])) {
$field_name = $this->options['item'][$namespace][$module][$element_name];
}
elseif (!empty($definition['group']) && !empty($this->options['item'][$namespace][$module][$definition['group']][$element_name])) {
$field_name = $this->options['item'][$namespace][$module][$definition['group']][$element_name];
}
else {
$field_name = NULL;
}
// Assign values for all elements, not only those defined in view settings.
// If element value is not defined in view settings, let's just assign NULL.
// It will not be passed to final theme function anyway during processing
// taking place in template_preprocess_views_view_views_rss().
if (!empty($rendered_fields[$field_name])) {
$item[$module][$element] = $rendered_fields[$field_name];
}
else {
$item[$module][$element] = NULL;
}
// Keep raw values too.
if (!empty($raw_fields[$field_name])) {
$raw_item[$module][$element] = $raw_fields[$field_name];
}
}
}
}
$this->view->views_rss['raw_items'][$row->index] = $raw_item;
return $item;
}
/**
* Function render.
*/
public function render($row) {
static $row_index;
if (!isset($row_index)) {
$row_index = 0;
}
$item_elements = views_rss_get('item_elements');
$item_data = $this
->mapRow($row);
// Preprocess whole item array before preprocessing separate elements.
$hook = 'views_rss_preprocess_item';
$modules = \Drupal::moduleHandler()
->getImplementations($hook);
$item_variables = array(
'item' => &$item_data,
'view' => $this->view,
);
// Add raw row if generated based on raw item values provided by field formatter.
if (!empty($this->view->views_rss['raw_items'][$row->index])) {
$item_variables['raw'] = $this->view->views_rss['raw_items'][$row->index];
}
foreach ($modules as $module) {
\Drupal::moduleHandler()
->invoke($module, $hook, array(
$item_variables,
));
}
$item = new \stdClass();
$item->elements = array();
// Process each element separately.
foreach ($item_data as $module => $module_item_elements) {
foreach ($module_item_elements as $element => $value) {
// Avoid double encoding: the $value might be already encoded here,
// depending on the field configuration/processing, and because we know
// it will be encoded again when the whole feed array will be passed to
// Drupal render, let's make sure we decode it here first.
if (is_string($value)) {
$value = htmlspecialchars_decode($value, ENT_QUOTES);
}
// Start building XML element array compatible with Drupal render.
// TODO review this to ensure that no warnings are generated.
$rss_elements = array(
array(
'key' => $element,
'value' => $value,
),
);
// Preprocess element initial value if required.
if (isset($item_elements[$module][$element]['preprocess functions']) && is_array($item_elements[$module][$element]['preprocess functions'])) {
foreach ($item_elements[$module][$element]['preprocess functions'] as $preprocess_function) {
if (function_exists($preprocess_function)) {
$item_variables = array(
'elements' => &$rss_elements,
'item' => $item_data,
'view' => $this->view,
);
// Add raw item if provided by field formatter.
if (!empty($this->view->views_rss['raw_items'][$row->index][$module][$element])) {
$item_variables['raw'] = $this->view->views_rss['raw_items'][$row->index][$module][$element];
}
$preprocess_function($item_variables);
}
}
}
// If there is no value and no attributes (in case of self-closing elements)
// already set for the element at this stage, it is not going to be set
// at any point further, so the element should not be added to the feed.
foreach ($rss_elements as $key => $rss_element) {
if (empty($rss_element['value']) && empty($rss_element['attributes'])) {
unset($rss_elements[$key]);
}
}
if (empty($rss_elements)) {
continue;
}
// Special processing for title, description and link elements, as these
// are hardcoded both in template_preprocess_views_view_row_rss() and in
// views-view-row-rss.html.twig, and we try to keep the compatibility.
if ($element === 'title' || $element === 'link') {
$rss_element = reset($rss_elements);
$item->{$element} = $rss_element['value'];
}
elseif ($element === 'description') {
$rss_element = reset($rss_elements);
if (is_string($rss_element['value'])) {
$item->{$element} = [
'#markup' => $rss_element['value'],
];
}
else {
$item->{$element} = $rss_element['value'];
}
}
else {
$item->elements = array_merge($item->elements, $rss_elements);
}
}
}
// Merge RDF namespaces in the XML namespaces in case they are used
// further in the RSS content.
if (function_exists('rdf_get_namespaces') && !empty($this->view->style_plugin->options['namespaces']['add_rdf_namespaces'])) {
$xml_rdf_namespaces = array();
foreach (rdf_get_namespaces() as $prefix => $uri) {
$xml_rdf_namespaces['xmlns:' . $prefix] = $uri;
}
$this->view->style_plugin->namespaces += $xml_rdf_namespaces;
}
$build = [
'#theme' => $this
->themeFunctions(),
'#view' => $this->view,
'#options' => $this->options,
'#row' => $item,
'#field_alias' => isset($this->field_alias) ? $this->field_alias : '',
];
return $build;
}
/**
* Retrieves a views field value from the style plugin.
*
* @param int $index
* The index count of the row as expected by views_plugin_style::getField().
* @param string $field_id
* The ID assigned to the required field in the display.
*/
public function getField($index, $field_id) {
if (empty($this->view->style_plugin) || !is_object($this->view->style_plugin) || empty($field_id)) {
return '';
}
return $this->view->style_plugin
->getField($index, $field_id);
}
}
Members
Name | Modifiers | Type | Description | Overrides |
---|---|---|---|---|
DependencySerializationTrait:: |
protected | property | An array of entity type IDs keyed by the property name of their storages. | |
DependencySerializationTrait:: |
protected | property | An array of service IDs keyed by property name used for serialization. | |
DependencySerializationTrait:: |
public | function | 1 | |
DependencySerializationTrait:: |
public | function | 2 | |
MessengerTrait:: |
protected | property | The messenger. | 29 |
MessengerTrait:: |
public | function | Gets the messenger. | 29 |
MessengerTrait:: |
public | function | Sets the messenger. | |
PluginBase:: |
protected | property | Configuration information passed into the plugin. | 1 |
PluginBase:: |
public | property | Plugins's definition | |
PluginBase:: |
public | property | The display object this plugin is for. | |
PluginBase:: |
public | property | Options for this plugin will be held here. | |
PluginBase:: |
protected | property | The plugin implementation definition. | 1 |
PluginBase:: |
protected | property | The plugin_id. | |
PluginBase:: |
protected | property | Stores the render API renderer. | 3 |
PluginBase:: |
public | property | The top object of a view. | 1 |
PluginBase:: |
public | function |
Calculates dependencies for the configured plugin. Overrides DependentPluginInterface:: |
14 |
PluginBase:: |
public static | function |
Creates an instance of the plugin. Overrides ContainerFactoryPluginInterface:: |
62 |
PluginBase:: |
constant | A string which is used to separate base plugin IDs from the derivative ID. | ||
PluginBase:: |
public | function |
Clears a plugin. Overrides ViewsPluginInterface:: |
2 |
PluginBase:: |
protected | function | Do the work to filter out stored options depending on the defined options. | |
PluginBase:: |
public | function |
Filter out stored options depending on the defined options. Overrides ViewsPluginInterface:: |
|
PluginBase:: |
public | function |
Returns an array of available token replacements. Overrides ViewsPluginInterface:: |
|
PluginBase:: |
public | function |
Gets the base_plugin_id of the plugin instance. Overrides DerivativeInspectionInterface:: |
|
PluginBase:: |
public | function |
Gets the derivative_id of the plugin instance. Overrides DerivativeInspectionInterface:: |
|
PluginBase:: |
public | function |
Gets the definition of the plugin implementation. Overrides PluginInspectionInterface:: |
3 |
PluginBase:: |
public | function |
Gets the plugin_id of the plugin instance. Overrides PluginInspectionInterface:: |
|
PluginBase:: |
public | function |
Returns the plugin provider. Overrides ViewsPluginInterface:: |
|
PluginBase:: |
protected | function | Returns the render API renderer. | 1 |
PluginBase:: |
public | function |
Adds elements for available core tokens to a form. Overrides ViewsPluginInterface:: |
|
PluginBase:: |
public | function |
Returns a string with any core tokens replaced. Overrides ViewsPluginInterface:: |
|
PluginBase:: |
constant | Include entity row languages when listing languages. | ||
PluginBase:: |
constant | Include negotiated languages when listing languages. | ||
PluginBase:: |
public | function |
Initialize the plugin. Overrides ViewsPluginInterface:: |
8 |
PluginBase:: |
public | function | Determines if the plugin is configurable. | |
PluginBase:: |
protected | function | Makes an array of languages, optionally including special languages. | |
PluginBase:: |
public | function |
Return the human readable name of the display. Overrides ViewsPluginInterface:: |
|
PluginBase:: |
public static | function |
Moves form elements into fieldsets for presentation purposes. Overrides ViewsPluginInterface:: |
|
PluginBase:: |
public static | function |
Flattens the structure of form elements. Overrides ViewsPluginInterface:: |
|
PluginBase:: |
public static | function | Returns substitutions for Views queries for languages. | |
PluginBase:: |
protected | function | Fills up the options of the plugin with defaults. | |
PluginBase:: |
public | function |
Returns the summary of the settings in the display. Overrides ViewsPluginInterface:: |
6 |
PluginBase:: |
public | function |
Provide a full list of possible theme templates used by this style. Overrides ViewsPluginInterface:: |
1 |
PluginBase:: |
public static | function |
Lists the trusted callbacks provided by the implementing class. Overrides TrustedCallbackInterface:: |
6 |
PluginBase:: |
public | function |
Unpack options over our existing defaults, drilling down into arrays
so that defaults don't get totally blown away. Overrides ViewsPluginInterface:: |
|
PluginBase:: |
public | function |
Returns the usesOptions property. Overrides ViewsPluginInterface:: |
8 |
PluginBase:: |
protected | function | Replaces Views' tokens in a given string. The resulting string will be sanitized with Xss::filterAdmin. | 1 |
PluginBase:: |
constant | Query string to indicate the site default language. | ||
PluginBase:: |
public | function |
Constructs a PluginBase object. Overrides PluginBase:: |
|
RowPluginBase:: |
protected | property |
Denotes whether the plugin has an additional options form. Overrides PluginBase:: |
1 |
RowPluginBase:: |
public | function | Allow the style to do stuff before each row is rendered. | 4 |
RowPluginBase:: |
public | function |
Add anything to the query that we might need to. Overrides PluginBase:: |
2 |
RowPluginBase:: |
public | function |
Perform any necessary changes to the form values prior to storage.
There is no need for this function to actually store the data. Overrides PluginBase:: |
1 |
RowPluginBase:: |
public | function | Returns the usesFields property. | 4 |
RowPluginBase:: |
public | function |
Validate the options form. Overrides PluginBase:: |
1 |
RssFields:: |
protected | property |
Does the row plugin support to add fields to it's output. Overrides RowPluginBase:: |
|
RssFields:: |
public | function |
Function buildOptionsForm. Overrides RowPluginBase:: |
|
RssFields:: |
protected | function |
Function defineOptions. Overrides RowPluginBase:: |
|
RssFields:: |
public | function | Retrieves a views field value from the style plugin. | |
RssFields:: |
protected | function | Protected fuction mapRow. | |
RssFields:: |
public | function |
Function render. Overrides RowPluginBase:: |
|
RssFields:: |
public | function |
Validates whether views_rss_core module exists or not. Overrides PluginBase:: |
|
StringTranslationTrait:: |
protected | property | The string translation service. | 1 |
StringTranslationTrait:: |
protected | function | Formats a string containing a count of items. | |
StringTranslationTrait:: |
protected | function | Returns the number of plurals supported by a given language. | |
StringTranslationTrait:: |
protected | function | Gets the string translation service. | |
StringTranslationTrait:: |
public | function | Sets the string translation service to use. | 2 |
StringTranslationTrait:: |
protected | function | Translates a string to the current language or to a given language. | |
TrustedCallbackInterface:: |
constant | Untrusted callbacks throw exceptions. | ||
TrustedCallbackInterface:: |
constant | Untrusted callbacks trigger silenced E_USER_DEPRECATION errors. | ||
TrustedCallbackInterface:: |
constant | Untrusted callbacks trigger E_USER_WARNING errors. |