theme.inc 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240
  1. <?php
  2. /**
  3. * @file
  4. * Theme functions for Views RSS module.
  5. */
  6. /**
  7. * Template preprocessor for views-view-views-rss.tpl.php.
  8. */
  9. function template_preprocess_views_view_views_rss(&$variables) {
  10. $view = $variables['view'];
  11. // Start building the feed array compatible with format_xml_elements().
  12. $rss_feed = array(
  13. 'key' => 'rss',
  14. 'attributes' => array(
  15. 'version' => '2.0',
  16. ),
  17. 'value' => array(),
  18. );
  19. // Prepare namespaces and add them to feed array.
  20. // xml:base cannot be defined by hook_views_rss_namespaces() implementation,
  21. // as we don't want its value to be cached, it needs to be dynamic.
  22. $rss_feed['attributes']['xml:base'] = url('<front>', array('absolute' => TRUE));
  23. // All other namespaces are taken from hook_views_rss_namespaces() implementations.
  24. foreach (views_rss_get('namespaces') as $module => $module_namespaces) {
  25. foreach ($module_namespaces as $namespace => $definition) {
  26. // Check if definition provided through modules hooks
  27. // should be overwritten by module configuration.
  28. if (
  29. isset($view->style_plugin->options['namespaces'][$module][$namespace])
  30. && !empty($view->style_plugin->options['namespaces'][$module][$namespace])
  31. ) {
  32. $definition['uri'] = $view->style_plugin->options['namespaces'][$module][$namespace];
  33. }
  34. // Add namespace to feed array.
  35. if (isset($definition['uri']) && !empty($definition['uri'])) {
  36. // Namespaces with prefix, for example xml:base="" or xmlns:dc=""
  37. if (isset($definition['prefix']) && !empty($definition['prefix'])) {
  38. $namespace_key = $definition['prefix'] . ':' . $namespace;
  39. $rss_feed['attributes'][$namespace_key] = $definition['uri'];
  40. }
  41. // Namespaces without prefix, for example: content="" or foaf=""
  42. else {
  43. $rss_feed['attributes'][$namespace] = $definition['uri'];
  44. }
  45. }
  46. }
  47. }
  48. // Prepare <channel> elements and add them to feed array.
  49. $rss_channel = array();
  50. foreach (views_rss_get('channel_elements') as $module => $module_channel_elements) {
  51. foreach ($module_channel_elements as $element => $definition) {
  52. list($namespace, $element_name) = views_rss_extract_element_names($element, 'core');
  53. // Try to fetch namespace value from view configuration.
  54. if (isset($view->style_plugin->options['channel'][$namespace][$module][$element_name])) {
  55. $value = $view->style_plugin->options['channel'][$namespace][$module][$element_name];
  56. }
  57. // Otherwise check if it was provided by element definition.
  58. elseif (isset($definition['default_value'])) {
  59. $value = $definition['default_value'];
  60. }
  61. else {
  62. $value = NULL;
  63. }
  64. // Avoid double encoding: the $value might be already encoded here,
  65. // depending on the field configuration/processing, and because we know
  66. // it will be encoded again when the whole feed array will be passed to
  67. // format_xml_elements(), let's make sure we decode it here first.
  68. if (is_string($value)) {
  69. $value = decode_entities($value);
  70. }
  71. // Start building XML channel element array compatible with format_xml_elements().
  72. $rss_elements = array(
  73. array(
  74. 'key' => $element,
  75. 'value' => $value,
  76. ),
  77. );
  78. // Preprocess element value.
  79. if (isset($definition['preprocess functions']) && is_array($definition['preprocess functions'])) {
  80. foreach ($definition['preprocess functions'] as $preprocess_function) {
  81. if (function_exists($preprocess_function)) {
  82. $item_variables = array(
  83. 'elements' => &$rss_elements,
  84. 'item' => $view->style_plugin->options['channel'],
  85. 'view' => $view,
  86. );
  87. $preprocess_function($item_variables);
  88. }
  89. }
  90. }
  91. // If there is no value and no attributes (in case of self-closing elements)
  92. // already set for the element at this stage, it is not going to be set
  93. // at any point further, so the element should not be added to the feed.
  94. foreach ($rss_elements as $key => $rss_element) {
  95. if (empty($rss_element['value']) && empty($rss_element['attributes'])) {
  96. unset($rss_elements[$key]);
  97. }
  98. }
  99. if (empty($rss_elements)) continue;
  100. // Add XML element(s) to the channel array.
  101. $rss_channel = array_merge($rss_channel, $rss_elements);
  102. }
  103. }
  104. // Channel array should not be added to the feed array yet, as first
  105. // it needs to get populated with all <item> elements.
  106. // Prepare <item> elements and add them to the channel array.
  107. $item_elements = views_rss_get('item_elements');
  108. $items = $view->style_plugin->map_rows($variables['rows']);
  109. foreach ($items as $item_key => $item) {
  110. // Start building XML item element array compatible with format_xml_elements().
  111. $rss_item = array(
  112. 'key' => 'item',
  113. 'value' => array(),
  114. );
  115. // Preprocess whole item array before preprocessing separate elements.
  116. foreach (module_implements('views_rss_preprocess_item') as $module) {
  117. $preprocess_function = $module . '_views_rss_preprocess_item';
  118. $item_variables = array(
  119. 'item' => &$item,
  120. 'view' => $view,
  121. );
  122. // Add raw row if generated based on raw item values provided by field formatter.
  123. if (!empty($view->views_rss['raw_items'][$item_key])) {
  124. $item_variables['raw'] = $view->views_rss['raw_items'][$item_key];
  125. }
  126. $preprocess_function($item_variables);
  127. }
  128. // Process each element separately.
  129. foreach ($item as $module => $module_item_elements) {
  130. foreach ($module_item_elements as $element => $value) {
  131. // Avoid double encoding: the $value might be already encoded here,
  132. // depending on the field configuration/processing, and because we know
  133. // it will be encoded again when the whole feed array will be passed to
  134. // format_xml_elements(), let's make sure we decode it here first.
  135. if (is_string($value)) {
  136. $value = decode_entities($value);
  137. }
  138. // Start building XML element array compatible with format_xml_elements().
  139. $rss_elements = array(
  140. array(
  141. 'key' => $element,
  142. 'value' => $value,
  143. ),
  144. );
  145. // Preprocess element initial value if required.
  146. if (isset($item_elements[$module][$element]['preprocess functions']) && is_array($item_elements[$module][$element]['preprocess functions'])) {
  147. foreach ($item_elements[$module][$element]['preprocess functions'] as $preprocess_function) {
  148. if (function_exists($preprocess_function)) {
  149. $item_variables = array(
  150. 'elements' => &$rss_elements,
  151. 'item' => $item,
  152. 'view' => $view,
  153. );
  154. // Add raw item if provided by field formatter.
  155. if (!empty($view->views_rss['raw_items'][$item_key][$module][$element])) {
  156. $item_variables['raw'] = $view->views_rss['raw_items'][$item_key][$module][$element];
  157. }
  158. $preprocess_function($item_variables);
  159. }
  160. }
  161. }
  162. // If no preprocess function was defined, and we have received
  163. // #rss_element value (XML element array) from the formatter, it should
  164. // be added to the feed array without any further modifications.
  165. elseif (
  166. !empty($view->views_rss['raw_items'][$item_key][$module][$element])
  167. && is_array($view->views_rss['raw_items'][$item_key][$module][$element])
  168. ) {
  169. // At this point we don't know yet if we got #rss_elements in raw
  170. // values, so do not overwrite and empty main $rss_elements yet, just
  171. // start working with new $formatter_rss_elements - it could be
  172. // overwritten once we are sure we have all required values.
  173. $formatter_rss_elements = array();
  174. foreach ($view->views_rss['raw_items'][$item_key][$module][$element] as $raw_item) {
  175. if (!empty($raw_item['rendered']['#rss_element'])) {
  176. $formatter_rss_elements[] = $raw_item['rendered']['#rss_element'];
  177. }
  178. }
  179. // Now we can overwrite main $rss_elements.
  180. if (!empty($formatter_rss_elements)) {
  181. $rss_elements = $formatter_rss_elements;
  182. }
  183. }
  184. // If there is no value and no attributes (in case of self-closing elements)
  185. // already set for the element at this stage, it is not going to be set
  186. // at any point further, so the element should not be added to the feed.
  187. foreach ($rss_elements as $key => $rss_element) {
  188. if (empty($rss_element['value']) && empty($rss_element['attributes'])) {
  189. unset($rss_elements[$key]);
  190. }
  191. }
  192. if (empty($rss_elements)) continue;
  193. // Add XML element(s) to the item array.
  194. $rss_item['value'] = array_merge($rss_item['value'], $rss_elements);
  195. }
  196. }
  197. // Add XML item element to the channe; array.
  198. $rss_channel[] = $rss_item;
  199. }
  200. // Finally, let's put together the whole feed array.
  201. $rss_feed['value'][] = array(
  202. 'key' => 'channel',
  203. 'value' => $rss_channel,
  204. );
  205. // Allow for altering it before final render and passing it to the template.
  206. drupal_alter('views_rss_feed', $rss_feed);
  207. // Assign rendered feed to the template variables.
  208. $variables['rss_feed'] = format_xml_elements(array($rss_feed));
  209. // Set XML header.
  210. drupal_add_http_header('Content-Type', 'application/rss+xml; charset=utf-8');
  211. }