views_rss_core.module 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285
  1. <?php
  2. /**
  3. * @file
  4. * Provides core <channel> and <item> elements for Views RSS module.
  5. */
  6. /**
  7. * Module installation path.
  8. */
  9. define('VIEWS_RSS_CORE_PATH', drupal_get_path('module', 'views_rss_core'));
  10. /**
  11. * Include file with field formatters.
  12. */
  13. include_once VIEWS_RSS_CORE_PATH .'/views_rss_core.field.inc';
  14. /**
  15. * Include file with all preprocess functions.
  16. */
  17. include_once VIEWS_RSS_CORE_PATH . '/views_rss_core.inc';
  18. /**
  19. * Implementation of hook_views_rss_namespaces().
  20. */
  21. function views_rss_core_views_rss_namespaces() {
  22. $namespaces['atom'] = array(
  23. 'prefix' => 'xmlns',
  24. 'uri' => 'http://www.w3.org/2005/Atom',
  25. );
  26. return $namespaces;
  27. }
  28. /**
  29. * Implements hook_views_rss_channel_elements().
  30. */
  31. function views_rss_core_views_rss_channel_elements() {
  32. $elements['title'] = array(
  33. 'configurable' => FALSE,
  34. 'preprocess functions' => array('views_rss_core_preprocess_channel_title'),
  35. 'help' => 'http://www.rssboard.org/rss-profile#element-channel-title',
  36. );
  37. $elements['description'] = array(
  38. 'description' => t('Description for this feed. If left blank, the default site mission will be used.'),
  39. 'settings form' => array('#type' => 'textarea', '#rows' => 3),
  40. 'preprocess functions' => array(
  41. 'views_rss_core_preprocess_channel_description',
  42. 'views_rss_rewrite_relative_paths',
  43. ),
  44. 'help' => 'http://www.rssboard.org/rss-profile#element-channel-description',
  45. );
  46. $elements['link'] = array(
  47. 'configurable' => FALSE,
  48. 'preprocess functions' => array('views_rss_core_preprocess_channel_link'),
  49. 'help' => 'http://www.rssboard.org/rss-profile#element-channel-link',
  50. );
  51. $elements['atom:link'] = array(
  52. 'configurable' => FALSE,
  53. 'preprocess functions' => array('views_rss_core_preprocess_channel_atom_link'),
  54. 'help' => 'http://www.rssboard.org/rss-profile#namespace-elements-atom-link',
  55. );
  56. $elements['language'] = array(
  57. 'preprocess functions' => array('views_rss_core_preprocess_channel_language'),
  58. 'description' => t("The language the channel is written in. This allows aggregators to group all Italian language sites, for example, on a single page. See list of <a href='@w3c_url'>allowable values</a> for this element defined by the W3C. If left empty, it will use current site's language.", array(
  59. '@w3c_url' => url('http://www.w3.org/TR/REC-html40/struct/dirlang.html', array('fragment' => 'langcodes')),
  60. )),
  61. 'help' => 'http://www.rssboard.org/rss-profile#element-channel-language',
  62. );
  63. $elements['category'] = array(
  64. 'description' => t('Specify one or more categories that the channel belongs to. Separate multiple items with comma.'),
  65. 'preprocess functions' => array('views_rss_core_preprocess_channel_category'),
  66. 'help' => 'http://www.rssboard.org/rss-profile#element-channel-category',
  67. );
  68. $elements['image'] = array(
  69. 'description' => t('Path to the image to be used as the artwork for your feed, for example <em>sites/default/files/AllAboutEverything.jpg</em>. Allowed image formats are GIF, JPEG or PNG. Maximum image width is 144 pixels, maximum height 400 pixels.'),
  70. 'preprocess functions' => array('views_rss_core_preprocess_channel_image'),
  71. 'help' => 'http://www.rssboard.org/rss-profile#element-channel-image',
  72. );
  73. $elements['copyright'] = array(
  74. 'description' => t('Copyright notice for content in the channel.'),
  75. 'help' => 'http://www.rssboard.org/rss-profile#element-channel-copyright',
  76. );
  77. $elements['managingEditor'] = array(
  78. 'description' => t('Email address for person responsible for editorial content.'),
  79. 'help' => 'http://www.rssboard.org/rss-profile#element-channel-managingeditor',
  80. );
  81. $elements['webMaster'] = array(
  82. 'description' => t('Email address for person responsible for technical issues relating to channel.'),
  83. 'help' => 'http://www.rssboard.org/rss-profile#element-channel-webmaster',
  84. );
  85. $elements['generator'] = array(
  86. 'description' => t('A string indicating the program used to generate the channel.'),
  87. 'help' => 'http://www.rssboard.org/rss-profile#element-channel-generator',
  88. );
  89. $elements['docs'] = array(
  90. 'description' => t("A URL that points to the documentation for the format used in the RSS file. It's for people who might stumble across an RSS file on a Web server 25 years from now and wonder what it is."),
  91. 'help' => 'http://www.rssboard.org/rss-profile#element-channel-docs',
  92. );
  93. $elements['cloud'] = array(
  94. 'description' => t("Allows processes to register with a cloud to be notified of updates to the channel, implementing a lightweight publish-subscribe protocol for RSS feeds. Example: <em>soap://rpc.sys.com:80/RPC2#pingMe</em>"),
  95. 'preprocess functions' => array('views_rss_core_preprocess_channel_cloud'),
  96. 'help' => 'http://www.rssboard.org/rss-profile#element-channel-cloud',
  97. );
  98. $elements['ttl'] = array(
  99. 'description' => t("ttl stands for time to live. It's a number of minutes that indicates how long a channel can be cached before refreshing from the source."),
  100. 'help' => 'http://www.rssboard.org/rss-profile#element-channel-ttl',
  101. );
  102. $elements['skipHours'] = array(
  103. 'description' => t('A hint for aggregators telling them which hours they can skip. The hours must be expressed as an integer representing the number of hours since 00:00:00 GMT. Values from 0 to 23 are permitted, with 0 representing midnight. An hour must not be duplicated.'),
  104. 'preprocess functions' => array('views_rss_core_preprocess_channel_skip'),
  105. 'help' => 'http://www.rssboard.org/rss-profile#element-channel-skiphours',
  106. );
  107. $elements['skipDays'] = array(
  108. 'description' => t('A hint for aggregators telling them which days of the week they can skip (up to seven days).'),
  109. 'preprocess functions' => array('views_rss_core_preprocess_channel_skip'),
  110. 'help' => 'http://www.rssboard.org/rss-profile#element-channel-skipdays',
  111. );
  112. $elements['pubDate'] = array(
  113. 'configurable' => FALSE,
  114. 'preprocess functions' => array('views_rss_core_preprocess_channel_date'),
  115. 'help' => 'http://www.rssboard.org/rss-profile#element-channel-pubdate',
  116. );
  117. $elements['lastBuildDate'] = array(
  118. 'configurable' => FALSE,
  119. 'preprocess functions' => array('views_rss_core_preprocess_channel_date'),
  120. 'help' => 'http://www.rssboard.org/rss-profile#element-channel-lastbuilddate',
  121. );
  122. return $elements;
  123. }
  124. /**
  125. * Implements hook_views_rss_item_elements().
  126. */
  127. function views_rss_core_views_rss_item_elements() {
  128. $elements['title'] = array(
  129. 'description' => t('The title of the item. Required by RSS specification.'),
  130. 'help' => 'http://www.rssboard.org/rss-profile#element-channel-item-title',
  131. );
  132. $elements['link'] = array(
  133. 'description' => t('The URL of the item. Required by RSS specification.'),
  134. 'help' => 'http://www.rssboard.org/rss-profile#element-channel-item-link',
  135. );
  136. $elements['description'] = array(
  137. 'description' => t('The item synopsis. Required by RSS specification.'),
  138. 'preprocess functions' => array('views_rss_rewrite_relative_paths'),
  139. 'help' => 'http://www.rssboard.org/rss-profile#element-channel-item-description',
  140. );
  141. $elements['author'] = array(
  142. 'description' => t('Email address of the author of the item. A feed published by an individual should omit this element and use the &lt;managingEditor&gt; or &lt;webMaster&gt; channel elements to provide contact information.'),
  143. 'help' => 'http://www.rssboard.org/rss-profile#element-channel-item-author',
  144. );
  145. $elements['category'] = array(
  146. 'description' => t('Includes the item in one or more categories.'),
  147. 'help' => 'http://www.rssboard.org/rss-profile#element-channel-item-category',
  148. );
  149. $elements['comments'] = array(
  150. 'description' => t('URL of a page for comments relating to the item.'),
  151. 'help' => 'http://www.rssboard.org/rss-profile#element-channel-item-comments',
  152. );
  153. $elements['enclosure'] = array(
  154. 'description' => t('Describes a media object that is attached to the item.'),
  155. 'help' => 'http://www.rssboard.org/rss-profile#element-channel-item-enclosure',
  156. );
  157. $elements['guid'] = array(
  158. 'description' => t('A string that uniquely identifies the item.'),
  159. 'preprocess functions' => array('views_rss_core_preprocess_item_guid'),
  160. 'help' => 'http://www.rssboard.org/rss-profile#element-channel-item-guid',
  161. );
  162. $elements['pubDate'] = array(
  163. 'description' => t('Indicates when the item was published.'),
  164. 'help' => 'http://www.rssboard.org/rss-profile#element-channel-item-pubdate',
  165. );
  166. $elements['source'] = array(
  167. 'configurable' => FALSE,
  168. 'description' => t('The RSS channel that the item came from.'),
  169. 'preprocess functions' => array('views_rss_core_preprocess_item_source'),
  170. 'help' => 'http://www.rssboard.org/rss-profile#element-channel-item-source',
  171. );
  172. return $elements;
  173. }
  174. /**
  175. * Implements hook_views_rss_date_sources().
  176. */
  177. function views_rss_core_views_rss_date_sources() {
  178. $sources['node'] = array(
  179. 'pubDate' => array(
  180. 'table' => 'node',
  181. 'field' => 'created',
  182. ),
  183. 'lastBuildDate' => array(
  184. 'table' => 'node',
  185. 'field' => 'changed',
  186. ),
  187. );
  188. $sources['node_revisions'] = array(
  189. 'pubDate' => array(
  190. 'table' => 'node_revisions',
  191. 'field' => 'timestamp',
  192. ),
  193. );
  194. $sources['comments'] = array(
  195. 'lastBuildDate' => array(
  196. 'table' => 'comments',
  197. 'field' => 'timestamp',
  198. ),
  199. );
  200. $sources['files'] = array(
  201. 'pubDate' => array(
  202. 'table' => 'files',
  203. 'field' => 'timestamp',
  204. ),
  205. );
  206. $sources['users'] = array(
  207. 'pubDate' => array(
  208. 'table' => 'users',
  209. 'field' => 'created',
  210. ),
  211. );
  212. return $sources;
  213. }
  214. /**
  215. * Implements hook_views_query_alter().
  216. */
  217. function views_rss_core_views_query_alter(&$view, &$query) {
  218. if ($view->style_plugin->definition['handler'] == 'views_rss_plugin_style_fields') {
  219. $date_sources = views_rss_get('date_sources');
  220. foreach (array_keys($date_sources) as $module) {
  221. if (isset($date_sources[$module][$view->base_table])) {
  222. // Select the most recent node creation date for <pubDate> element.
  223. if (isset($date_sources[$module][$view->base_table]['pubDate'])) {
  224. $query->fields['pubDate'] = $date_sources[$module][$view->base_table]['pubDate'];
  225. }
  226. // Select the most recent node update date for <lastBuildDate> element.
  227. if (isset($date_sources[$module][$view->base_table]['lastBuildDate'])) {
  228. $query->fields['lastBuildDate'] = $date_sources[$module][$view->base_table]['lastBuildDate'];
  229. }
  230. }
  231. }
  232. }
  233. }
  234. /**
  235. * Implements hook_views_rss_options_form_validate().
  236. */
  237. function views_rss_core_views_rss_options_form_validate($form, &$form_state) {
  238. // Validate channel <image> element.
  239. if (!empty($form_state['values']['style_options']['channel']['core']['views_rss_core']['image'])) {
  240. // Do not validate absolute URLs, as this could mean external image.
  241. if (!valid_url($form_state['values']['style_options']['channel']['core']['views_rss_core']['image'], TRUE)) {
  242. // Check that image exists and is in acceptable format.
  243. $image = image_load($form_state['values']['style_options']['channel']['core']['views_rss_core']['image']);
  244. if (empty($image)) {
  245. form_set_error('style_options][channel][core][views_rss_core][image', t('Unable to find %image or incorrect image format.', array(
  246. '%image' => $form_state['values']['style_options']['channel']['core']['views_rss_core']['image'],
  247. )));
  248. }
  249. else {
  250. // Check image width.
  251. if ($image->info['width'] > 144) {
  252. form_set_error('style_options][channel][core][views_rss_core][image', t("Maximum allowed width of an image for feed channel's &lt;image&gt; element is 144 pixels. Specified %image is !width pixels wide.", array(
  253. '%image' => $form_state['values']['style_options']['channel']['core']['views_rss_core']['image'],
  254. '!width' => $image->info['width'],
  255. )));
  256. }
  257. // Check image height.
  258. if ($image->info['height'] > 400) {
  259. form_set_error('style_options][channel][core][views_rss_core][image', t("Maximum allowed height of an image for feed channel's &lt;image&gt; element is 400 pixels. Specified %image is !height pixels high.", array(
  260. '%image' => $form_state['values']['style_options']['channel']['core']['views_rss_core']['image'],
  261. '!height' => $image->info['height'],
  262. )));
  263. }
  264. }
  265. }
  266. }
  267. // Validate channel <docs> element.
  268. if (!empty($form_state['values']['style_options']['channel']['core']['views_rss_core']['docs'])) {
  269. if (!valid_url($form_state['values']['style_options']['channel']['core']['views_rss_core']['docs'], TRUE)) {
  270. form_set_error('style_options][channel][core][views_rss_core][docs', t("Not a valid URL."));
  271. }
  272. }
  273. }