views_data_export.theme.inc 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480
  1. <?php
  2. /**
  3. * @file
  4. * Theme related functions for processing our output style plugins.
  5. *
  6. * Views bug: http://drupal.org/node/593336
  7. */
  8. /**
  9. * Theme a status message
  10. */
  11. function theme_views_data_export_message($var) {
  12. $output = '';
  13. $output .= '<div class="messages status ' . $var['type'] . '">';
  14. $output .= $var['message'];
  15. $output .= '</div>';
  16. return $output;
  17. }
  18. /**
  19. * Theme a feed link.
  20. *
  21. * This theme function uses the theme pattern system to allow it to be
  22. * overidden in a more specific manner. The options for overiding this include
  23. * providing per display id; per type; per display id and per type.
  24. *
  25. * e.g.
  26. * For the view "export_test" with the display "page_1" and the type "csv" you
  27. * would have the following options.
  28. * views_data_export_feed_icon__export_test__page_1__csv
  29. * views_data_export_feed_icon__export_test__page_1
  30. * views_data_export_feed_icon__export_test__csv
  31. * views_data_export_feed_icon__page_1__csv
  32. * views_data_export_feed_icon__page_1
  33. * views_data_export_feed_icon__csv
  34. * views_data_export_feed_icon
  35. *
  36. * @ingroup themeable
  37. */
  38. function theme_views_data_export_feed_icon($variables) {
  39. extract($variables, EXTR_SKIP);
  40. $url_options = array('html' => true);
  41. if ($query) {
  42. $url_options['query'] = $query;
  43. }
  44. $image = theme('image', array('path' => $image_path, 'alt' => $text, 'title' => $text));
  45. return l($image, $url, $url_options);
  46. }
  47. /**
  48. * Theme callback for the export complete page.
  49. *
  50. * @param $file
  51. * Link to output file
  52. */
  53. function theme_views_data_export_complete_page($variables) {
  54. extract($variables, EXTR_SKIP);
  55. drupal_set_title(t('Data export successful'));
  56. drupal_add_html_head(array('#tag' => 'meta', '#attributes' => array('http-equiv' =>"refresh", 'content' => '3;url='. $file)), 'views_data_export_download');
  57. $output = '';
  58. $output .= '<p>';
  59. $output .= t('Your export has been created. View/download the file <a href="@link">here</a> (will automatically download in 3 seconds.)', array('@link' => $file));
  60. $output .= '</p>';
  61. if (!empty($return_url)) {
  62. $output .= '<p>';
  63. $output .= l(t('Return to previous page'), $return_url);
  64. $output .= '</p>';
  65. }
  66. return $output;
  67. }
  68. function template_preprocess_views_data_export(&$vars) {
  69. $vars['header'] = $vars['rows']['header'];
  70. $vars['body'] = $vars['rows']['body'];
  71. $vars['footer'] = $vars['rows']['footer'];
  72. $view = $vars['view'];
  73. $fields = &$view->field;
  74. }
  75. function template_preprocess_views_data_export_csv_header(&$vars) {
  76. _views_data_export_header_shared_preprocess($vars);
  77. // Make sure we catch saved options that are misspelled. LEGACY
  78. if (isset($vars['options']['seperator'])) {
  79. $vars['options']['separator'] = $vars['options']['seperator'];
  80. }
  81. // Support old misspelled templates. LEGACY
  82. $vars['seperator'] =
  83. $vars['separator'] = $vars['options']['separator'];
  84. // Special handling when quoted values are involved.
  85. if ($vars['options']['quote']) {
  86. $wrap = '"';
  87. $replace_value = '""';
  88. }
  89. else {
  90. $wrap = '';
  91. $replace_value = '';
  92. }
  93. // Format header values.
  94. foreach ($vars['header'] as $key => $value) {
  95. $output = decode_entities(strip_tags($value));
  96. if (!empty($vars['options']['trim'])) {
  97. $output = trim($output);
  98. }
  99. if (!empty($vars['options']['encoding']) && function_exists('iconv')) {
  100. switch($vars['options']['encoding']) {
  101. case 'ASCII':
  102. $converted = iconv("UTF-8", "ASCII//TRANSLIT", $output);
  103. if ($converted !== FALSE) {
  104. $output = $converted;
  105. }
  106. break;
  107. }
  108. }
  109. $vars['header'][$key] = $wrap . str_replace('"', $replace_value, $output) . $wrap;
  110. }
  111. }
  112. function template_preprocess_views_data_export_csv_body(&$vars) {
  113. _views_data_export_body_shared_preprocess($vars);
  114. // Make sure we catch saved options that are misspelled. LEGACY
  115. if (isset($vars['options']['seperator'])) {
  116. $vars['options']['separator'] = $vars['options']['seperator'];
  117. }
  118. // Support old misspelled templates. LEGACY
  119. $vars['seperator'] =
  120. $vars['separator'] = $vars['options']['separator'];
  121. // Special handling when quoted values are involved.
  122. if ($vars['options']['quote']) {
  123. $wrap = '"';
  124. $replace_value = '""';
  125. }
  126. else {
  127. $wrap = '';
  128. $replace_value = '';
  129. }
  130. // Format row values.
  131. foreach ($vars['themed_rows'] as $i => $values) {
  132. foreach ($values as $j => $value) {
  133. $output = decode_entities(strip_tags($value));
  134. if (!empty($vars['options']['trim'])) {
  135. $output = trim($output);
  136. }
  137. if (!empty($vars['options']['encoding']) && function_exists('iconv')) {
  138. switch($vars['options']['encoding']) {
  139. case 'ASCII':
  140. $converted = iconv("UTF-8", "ASCII//TRANSLIT", $output);
  141. if ($converted !== FALSE) {
  142. $output = $converted;
  143. }
  144. break;
  145. }
  146. }
  147. if (!empty($vars['options']['replace_newlines'])) {
  148. $output = str_replace("\n", $vars['options']['newline_replacement'], $output);
  149. }
  150. $vars['themed_rows'][$i][$j] = $wrap . str_replace('"', $replace_value, $output) . $wrap;
  151. }
  152. }
  153. }
  154. /**
  155. * Preprocess csv output template.
  156. */
  157. function template_preprocess_views_data_export_csv(&$vars) {
  158. // TODO Replace items with themed_rows.
  159. _views_data_export_shared_preprocess($vars);
  160. // Make sure we catch saved options that are misspelled. LEGACY
  161. if (isset($vars['options']['separator'])) {
  162. $vars['options']['separator'] = $vars['options']['seperator'];
  163. }
  164. // Support old misspelled templates. LEGACY
  165. $vars['seperator'] =
  166. $vars['separator'] = $vars['options']['separator'];
  167. // Special handling when quoted values are involved.
  168. if ($vars['options']['quote']) {
  169. $wrap = '"';
  170. $replace_value = '""';
  171. }
  172. else {
  173. $wrap = '';
  174. $replace_value = '';
  175. }
  176. // Format header values.
  177. foreach ($vars['header'] as $key => $value) {
  178. $output = decode_entities(strip_tags($value));
  179. if ($vars['options']['trim']) {
  180. $output = trim($output);
  181. }
  182. if (!empty($vars['options']['encoding']) && function_exists('iconv')) {
  183. switch($vars['options']['encoding']) {
  184. case 'ASCII':
  185. $converted = iconv("UTF-8", "ASCII//TRANSLIT", $output);
  186. if ($converted !== FALSE) {
  187. $output = $converted;
  188. }
  189. break;
  190. }
  191. }
  192. $vars['header'][$key] = $wrap . str_replace('"', $replace_value, $output) . $wrap;
  193. }
  194. // Format row values.
  195. foreach ($vars['themed_rows'] as $i => $values) {
  196. foreach ($values as $j => $value) {
  197. $output = decode_entities(strip_tags($value));
  198. if ($vars['options']['trim']) {
  199. $output = trim($output);
  200. }
  201. if (!empty($vars['options']['encoding']) && function_exists('iconv')) {
  202. switch($vars['options']['encoding']) {
  203. case 'ASCII':
  204. $converted = iconv("UTF-8", "ASCII//TRANSLIT", $output);
  205. if ($converted !== FALSE) {
  206. $output = $converted;
  207. }
  208. break;
  209. }
  210. }
  211. $vars['themed_rows'][$i][$j] = $wrap . str_replace('"', $replace_value, $output) . $wrap;
  212. }
  213. }
  214. }
  215. /**
  216. * Preprocess txt output template.
  217. */
  218. function template_preprocess_views_data_export_txt_body(&$vars) {
  219. _views_data_export_header_shared_preprocess($vars);
  220. _views_data_export_body_shared_preprocess($vars);
  221. }
  222. function template_preprocess_views_data_export_doc_body(&$vars) {
  223. // Pass through the generic MS Office preprocess.
  224. template_preprocess_views_data_export_msoffice_body($vars);
  225. }
  226. function template_preprocess_views_data_export_xls_body(&$vars) {
  227. // Pass through the generic MS Office preprocess.
  228. template_preprocess_views_data_export_msoffice_body($vars);
  229. }
  230. function template_preprocess_views_data_export_msoffice_body(&$vars) {
  231. _views_data_export_header_shared_preprocess($vars);
  232. _views_data_export_body_shared_preprocess($vars);
  233. $output = '';
  234. // Construct the tbody of a table, see theme_table().
  235. $ts = tablesort_init($vars['header']);
  236. $flip = array(
  237. 'even' => 'odd',
  238. 'odd' => 'even',
  239. );
  240. $class = 'even';
  241. foreach ($vars['themed_rows'] as $number => $row) {
  242. $attributes = array();
  243. // Check if we're dealing with a simple or complex row
  244. if (isset($row['data'])) {
  245. foreach ($row as $key => $value) {
  246. if ($key == 'data') {
  247. $cells = $value;
  248. }
  249. else {
  250. $attributes[$key] = $value;
  251. }
  252. }
  253. }
  254. else {
  255. $cells = $row;
  256. }
  257. if (count($cells)) {
  258. // Add odd/even class
  259. $class = $flip[$class];
  260. if (isset($attributes['class'])) {
  261. $attributes['class'] .= ' ' . $class;
  262. }
  263. else {
  264. $attributes['class'] = $class;
  265. }
  266. // Build row
  267. $output .= ' <tr' . drupal_attributes($attributes) . '>';
  268. $i = 0;
  269. foreach ($cells as $cell) {
  270. $cell = tablesort_cell($cell, $vars['header'], $ts, $i++);
  271. $output .= _theme_table_cell($cell);
  272. }
  273. $output .= " </tr>\n";
  274. }
  275. }
  276. $vars['tbody'] = preg_replace('/<\/?(a|span) ?.*?>/', '', $output); // strip 'a' and 'span' tags
  277. }
  278. function template_preprocess_views_data_export_doc_header(&$vars) {
  279. // Pass through the generic MS Office preprocess.
  280. template_preprocess_views_data_export_msoffice_header($vars);
  281. }
  282. function template_preprocess_views_data_export_xls_header(&$vars) {
  283. // Pass through the generic MS Office preprocess.
  284. template_preprocess_views_data_export_msoffice_header($vars);
  285. }
  286. function template_preprocess_views_data_export_msoffice_header(&$vars) {
  287. _views_data_export_header_shared_preprocess($vars);
  288. // Need to do a little work to construct the table header, see theme_table().
  289. $vars['header_row'] = '';
  290. $vars['header_row'] .= '<thead><tr>';
  291. $ts = tablesort_init($vars['header']);
  292. foreach ($vars['header'] as $cell) {
  293. $cell = tablesort_header($cell, $vars['header'], $ts);
  294. $vars['header_row'] .= _theme_table_cell($cell, TRUE);
  295. }
  296. $vars['header_row'] .= '</tr></thead>';
  297. $vars['header_row'] = preg_replace('/<\/?(a|span) ?.*?>/', '', $vars['header_row']); // strip 'a' and 'span' tags
  298. }
  299. /**
  300. * Preprocess xml output template.
  301. */
  302. function template_preprocess_views_data_export_xml_header(&$vars) {
  303. // Compute the root XML node, using the base table, and appending an 's' if needed.
  304. $root_node = $vars['view']->base_table;
  305. if (rtrim($root_node, 's') == $root_node) {
  306. $root_node .= 's';
  307. }
  308. $vars['root_node'] = _views_data_export_xml_tag_clean($root_node);
  309. }
  310. /**
  311. * Preprocess xml output template.
  312. */
  313. function template_preprocess_views_data_export_xml_footer(&$vars) {
  314. // Compute the root XML node, using the base table, and appending an 's' if needed.
  315. $root_node = $vars['view']->base_table;
  316. if (rtrim($root_node, 's') == $root_node) {
  317. $root_node .= 's';
  318. }
  319. $vars['root_node'] = _views_data_export_xml_tag_clean($root_node);
  320. }
  321. /**
  322. * Preprocess xml output template.
  323. */
  324. function template_preprocess_views_data_export_xml_body(&$vars) {
  325. _views_data_export_header_shared_preprocess($vars);
  326. _views_data_export_body_shared_preprocess($vars);
  327. // Compute the tag name based on the views base table, minus any trailing 's'.
  328. $vars['item_node'] = _views_data_export_xml_tag_clean(rtrim($vars['view']->base_table, 's'));
  329. foreach ($vars['themed_rows'] as $num => $row) {
  330. foreach ($row as $field => $content) {
  331. // Prevent double encoding of the ampersand. Look for the entities produced by check_plain().
  332. $content = preg_replace('/&(?!(amp|quot|#039|lt|gt);)/', '&amp;', $content);
  333. // Convert < and > to HTML entities.
  334. $content = str_replace(
  335. array('<', '>'),
  336. array('&lt;', '&gt;'),
  337. $content);
  338. $vars['themed_rows'][$num][$field] = $content;
  339. }
  340. }
  341. foreach ($vars['header'] as $field => $header) {
  342. // If there is no field label, use 'no name'.
  343. $vars['xml_tag'][$field] = !empty($header) ? $header : 'no name';
  344. if ($vars['options']['transform']) {
  345. switch ($vars['options']['transform_type']) {
  346. case 'dash':
  347. $vars['xml_tag'][$field] = str_replace(' ', '-', $header);
  348. break;
  349. case 'underline':
  350. $vars['xml_tag'][$field] = str_replace(' ', '_', $header);
  351. break;
  352. case 'camel':
  353. $vars['xml_tag'][$field] = str_replace(' ', '', ucwords(strtolower($header)));
  354. // Convert the very first character of the string to lowercase.
  355. $vars['xml_tag'][$field][0] = strtolower($vars['xml_tag'][$field][0]);
  356. break;
  357. case 'pascal':
  358. $vars['xml_tag'][$field] = str_replace(' ', '', ucwords(strtolower($header)));
  359. break;
  360. }
  361. }
  362. // We should always try to output valid XML.
  363. $vars['xml_tag'][$field] = _views_data_export_xml_tag_clean($vars['xml_tag'][$field]);
  364. }
  365. }
  366. /**
  367. * Returns a valid XML tag formed from the given input.
  368. *
  369. * @param $tag The string that should be made into a valid XML tag.
  370. * @return The valid XML tag or an empty string if the string contained no valid
  371. * XML tag characters.
  372. */
  373. function _views_data_export_xml_tag_clean($tag) {
  374. // This regex matches characters that are not valid in XML tags, and the
  375. // unicode ones that are. We don't bother with unicode, because it would so
  376. // the preg_replace down a lot.
  377. static $invalid_tag_chars_regex = '#[^\:A-Za-z_\-.0-9]+#';
  378. // These characters are not valid at the start of an XML tag:
  379. static $invalid_start_chars = '-.0123456789';
  380. // Convert invalid chars to '-':
  381. $tag = preg_replace($invalid_tag_chars_regex, '-', $tag);
  382. // Need to trim invalid characters from the start of the string:
  383. $tag = ltrim($tag, $invalid_start_chars);
  384. return $tag;
  385. }
  386. /**
  387. * Shared helper function for export preprocess functions.
  388. */
  389. function _views_data_export_header_shared_preprocess(&$vars) {
  390. $view = $vars['view'];
  391. $fields = &$view->field;
  392. $vars['header'] = array();
  393. foreach ($fields as $key => $field) {
  394. if (empty($field->options['exclude'])) {
  395. $vars['header'][$key] = check_plain($field->label());
  396. }
  397. }
  398. }
  399. /**
  400. * Shared helper function for export preprocess functions.
  401. */
  402. function _views_data_export_body_shared_preprocess(&$vars) {
  403. $view = $vars['view'];
  404. $fields = &$view->field;
  405. $rows = $vars['rows'];
  406. $vars['themed_rows'] = array();
  407. $keys = array_keys($fields);
  408. foreach ($rows as $num => $row) {
  409. $vars['themed_rows'][$num] = array();
  410. foreach ($keys as $id) {
  411. if (empty($fields[$id]->options['exclude'])) {
  412. $vars['themed_rows'][$num][$id] = $view->style_plugin->rendered_fields[$num][$id];
  413. }
  414. }
  415. }
  416. }