date.theme 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411
  1. <?php
  2. /**
  3. * @file
  4. * Theme functions.
  5. */
  6. /**
  7. * @addtogroup themeable
  8. * @{
  9. *
  10. * Formatter themes
  11. */
  12. /**
  13. * Returns HTML for a date element formatted as a Start/End combination.
  14. *
  15. * $entity->date_id
  16. * If set, this will show only an individual date on a field with
  17. * multiple dates. The value should be a string that contains
  18. * the following values, separated with periods:
  19. * - module name of the module adding the item
  20. * - node nid
  21. * - field name
  22. * - delta value of the field to be displayed
  23. * - other information the module's custom theme might need
  24. *
  25. * Used by the calendar module and available for other uses.
  26. * example: 'date.217.field_date.3.test'
  27. *
  28. * $entity->date_repeat_show
  29. * If true, tells the theme to show all the computed values of a repeating
  30. * date. If not true or not set, only the start date and the repeat rule
  31. * will be displayed.
  32. *
  33. * $dates['format']
  34. * The format string used on these dates
  35. * $dates['value']['local']['object']
  36. * The local date object for the Start date
  37. * $dates['value2']['local']['object']
  38. * The local date object for the End date
  39. * $dates['value']['local']['datetime']
  40. * The datetime value of the Start date database (GMT) value
  41. * $dates['value2']['local']['datetime']
  42. * The datetime value of the End date database (GMT) value
  43. * $dates['value']['formatted']
  44. * Formatted Start date, i.e. 'February 15, 2007 2:00 pm';
  45. * $dates['value']['formatted_date']
  46. * Only the date part of the formatted Start date
  47. * $dates['value']['formatted_time']
  48. * Only the time part of the formatted Start date
  49. * $dates['value2']['formatted']
  50. * Formatted End date, i.e. 'February 15, 2007 6:00 pm';
  51. * $dates['value2']['formatted_date']
  52. * Only the date part of the formatted End date
  53. * $dates['value2']['formatted_time']
  54. * Only the time part of the formatted End date
  55. */
  56. function theme_date_display_combination($variables) {
  57. static $repeating_ids = array();
  58. $entity_type = $variables['entity_type'];
  59. $entity = $variables['entity'];
  60. $field = $variables['field'];
  61. $instance = $variables['instance'];
  62. $langcode = $variables['langcode'];
  63. $item = $variables['item'];
  64. $delta = $variables['delta'];
  65. $display = $variables['display'];
  66. $field_name = $field['field_name'];
  67. $formatter = $display['type'];
  68. $options = $display['settings'];
  69. $dates = $variables['dates'];
  70. $attributes = $variables['attributes'];
  71. $rdf_mapping = $variables['rdf_mapping'];
  72. $add_rdf = $variables['add_rdf'];
  73. $microdata = $variables['microdata'];
  74. $add_microdata = $variables['add_microdata'];
  75. $precision = date_granularity_precision($field['settings']['granularity']);
  76. $output = '';
  77. // If date_id is set for this field and delta doesn't match, don't display it.
  78. if (!empty($entity->date_id)) {
  79. foreach ((array) $entity->date_id as $key => $id) {
  80. list($module, $nid, $field_name, $item_delta, $other) = explode('.', $id . '.');
  81. if ($field_name == $field['field_name'] && isset($delta) && $item_delta != $delta) {
  82. return $output;
  83. }
  84. }
  85. }
  86. // Check the formatter settings to see if the repeat rule should be displayed.
  87. // Show it only with the first multiple value date.
  88. list($id) = entity_extract_ids($entity_type, $entity);
  89. if (!in_array($id, $repeating_ids) && module_exists('date_repeat_field') && !empty($item['rrule']) && $options['show_repeat_rule'] == 'show') {
  90. $repeat_vars = array(
  91. 'field' => $field,
  92. 'item' => $item,
  93. 'entity_type' => $entity_type,
  94. 'entity' => $entity,
  95. );
  96. $output .= theme('date_repeat_display', $repeat_vars);
  97. $repeating_ids[] = $id;
  98. }
  99. // If this is a full node or a pseudo node created by grouping multiple
  100. // values, see exactly which values are supposed to be visible.
  101. if (isset($entity->$field_name)) {
  102. $entity = date_prepare_entity($formatter, $entity_type, $entity, $field, $instance, $langcode, $item, $display);
  103. // Did the current value get removed by formatter settings?
  104. if (empty($entity->{$field_name}[$langcode][$delta])) {
  105. return $output;
  106. }
  107. // Adjust the $element values to match the changes.
  108. $element['#entity'] = $entity;
  109. }
  110. switch ($options['fromto']) {
  111. case 'value':
  112. $date1 = $dates['value']['formatted'];
  113. $date2 = $date1;
  114. break;
  115. case 'value2':
  116. $date2 = $dates['value2']['formatted'];
  117. $date1 = $date2;
  118. break;
  119. default:
  120. $date1 = $dates['value']['formatted'];
  121. $date2 = $dates['value2']['formatted'];
  122. break;
  123. }
  124. // Pull the timezone, if any, out of the formatted result and tack it back on
  125. // at the end, if it is in the current formatted date.
  126. $timezone = $dates['value']['formatted_timezone'];
  127. if ($timezone) {
  128. $timezone = ' ' . $timezone;
  129. }
  130. $date1 = str_replace($timezone, '', $date1);
  131. $date2 = str_replace($timezone, '', $date2);
  132. $time1 = preg_replace('`^([\(\[])`', '', $dates['value']['formatted_time']);
  133. $time1 = preg_replace('([\)\]]$)', '', $time1);
  134. $time2 = preg_replace('`^([\(\[])`', '', $dates['value2']['formatted_time']);
  135. $time2 = preg_replace('([\)\]]$)', '', $time2);
  136. // A date with a granularity of 'hour' has a time string that is an integer
  137. // value. We can't use that to replace time strings in formatted dates.
  138. $has_time_string = date_has_time($field['settings']['granularity']);
  139. if ($precision == 'hour') {
  140. $has_time_string = FALSE;
  141. }
  142. // No date values, display nothing.
  143. if (empty($date1) && empty($date2)) {
  144. $output .= '';
  145. }
  146. // Start and End dates match or there is no End date, display a complete
  147. // single date.
  148. elseif ($date1 == $date2 || empty($date2)) {
  149. $output .= theme('date_display_single', array(
  150. 'date' => $date1,
  151. 'timezone' => $timezone,
  152. 'attributes' => $attributes,
  153. 'rdf_mapping' => $rdf_mapping,
  154. 'add_rdf' => $add_rdf,
  155. 'microdata' => $microdata,
  156. 'add_microdata' => $add_microdata,
  157. 'dates' => $dates,
  158. ));
  159. }
  160. // Same day, different times, don't repeat the date but show both Start and
  161. // End times. We can NOT do this if the replacement value is an integer
  162. // instead of a time string.
  163. elseif ($has_time_string && $dates['value']['formatted_date'] == $dates['value2']['formatted_date']) {
  164. // Replace the original time with the start/end time in the formatted start
  165. // date. Make sure that parentheses or brackets wrapping the time will be
  166. // retained in the final result.
  167. $time = theme('date_display_range', array(
  168. 'date1' => $time1,
  169. 'date2' => $time2,
  170. 'timezone' => $timezone,
  171. 'attributes' => $attributes,
  172. 'rdf_mapping' => $rdf_mapping,
  173. 'add_rdf' => $add_rdf,
  174. 'microdata' => $microdata,
  175. 'add_microdata' => $add_microdata,
  176. 'dates' => $dates,
  177. ));
  178. $replaced = str_replace($time1, $time, $date1);
  179. $output .= theme('date_display_single', array(
  180. 'date' => $replaced,
  181. 'timezone' => $timezone,
  182. 'attributes' => array(),
  183. 'rdf_mapping' => array(),
  184. 'add_rdf' => FALSE,
  185. 'dates' => $dates,
  186. ));
  187. }
  188. // Different days, display both in their entirety.
  189. else {
  190. $output .= theme('date_display_range', array(
  191. 'date1' => $date1,
  192. 'date2' => $date2,
  193. 'timezone' => $timezone,
  194. 'attributes' => $attributes,
  195. 'rdf_mapping' => $rdf_mapping,
  196. 'add_rdf' => $add_rdf,
  197. 'microdata' => $microdata,
  198. 'add_microdata' => $add_microdata,
  199. 'dates' => $dates,
  200. ));
  201. }
  202. return $output;
  203. }
  204. /**
  205. * Template preprocess function for displaying a single date.
  206. */
  207. function template_preprocess_date_display_single(&$variables) {
  208. if ($variables['add_rdf'] || !empty($variables['add_microdata'])) {
  209. // Pass along the rdf mapping for this field, if any. Add some default rdf
  210. // attributes that will be used if not overridden by attributes passed in.
  211. $rdf_mapping = $variables['rdf_mapping'];
  212. $base_attributes = array(
  213. 'property' => array('dc:date'),
  214. 'datatype' => 'xsd:dateTime',
  215. 'content' => $variables['dates']['value']['formatted_iso'],
  216. );
  217. $variables['attributes'] = $variables['attributes'] + $base_attributes;
  218. }
  219. // Pass along microdata attributes, or set display to false if none are set.
  220. if (!empty($variables['add_microdata'])) {
  221. // Because the Entity API integration for Date has a variable data
  222. // structure depending on whether there is an end value, the attributes
  223. // could be attached to the field or to the value property.
  224. if(!empty($variables['microdata']['#attributes']['itemprop'])) {
  225. $variables['microdata']['value']['#attributes'] = $variables['microdata']['#attributes'];
  226. }
  227. // Add the machine readable time using the content attribute.
  228. if(!empty($variables['microdata']['value']['#attributes'])) {
  229. $variables['microdata']['value']['#attributes']['content'] = $variables['dates']['value']['formatted_iso'];
  230. }
  231. else {
  232. $variables['add_microdata'] = FALSE;
  233. }
  234. }
  235. }
  236. /**
  237. * Returns HTML for a date element formatted as a single date.
  238. */
  239. function theme_date_display_single($variables) {
  240. $date = $variables['date'];
  241. $timezone = $variables['timezone'];
  242. $attributes = $variables['attributes'];
  243. // Wrap the result with the attributes.
  244. $output = '<span class="date-display-single"' . drupal_attributes($attributes) . '>' . $date . $timezone . '</span>';
  245. if (!empty($variables['add_microdata'])) {
  246. $output .= '<meta' . drupal_attributes($variables['microdata']['value']['#attributes']) . '/>';
  247. }
  248. return $output;
  249. }
  250. /**
  251. * Template preprocess function for displaying a range of dates.
  252. */
  253. function template_preprocess_date_display_range(&$variables) {
  254. // Merge in the shared attributes for themes to use.
  255. $variables['attributes_start'] += $variables['attributes'];
  256. $variables['attributes_end'] += $variables['attributes'];
  257. if ($variables['add_rdf']) {
  258. // Pass along the rdf mapping for this field, if any. Add some default rdf
  259. // attributes that will be used if not overridden by attributes passed in.
  260. $dates = $variables['dates'];
  261. $base_attributes = array(
  262. 'property' => array('dc:date'),
  263. 'datatype' => 'xsd:dateTime',
  264. 'content' => $dates['value']['formatted_iso'],
  265. );
  266. $variables['attributes_start'] += $base_attributes;
  267. $variables['attributes_end'] += $base_attributes;
  268. $variables['attributes_end']['content'] = $dates['value2']['formatted_iso'];
  269. foreach ($variables['attributes_end']['property'] as $delta => $property) {
  270. $variables['attributes_end']['property'][$delta] = str_replace('start', 'end', $property);
  271. }
  272. }
  273. // Pass along microdata attributes, or set display to false if none are set.
  274. if ($variables['add_microdata']) {
  275. if (!empty($variables['microdata']['value']['#attributes'])) {
  276. $variables['microdata']['value']['#attributes']['content'] = $variables['dates']['value']['formatted_iso'];
  277. $variables['microdata']['value2']['#attributes']['content'] = $variables['dates']['value2']['formatted_iso'];
  278. }
  279. else {
  280. $variables['add_microdata'] = FALSE;
  281. }
  282. }
  283. }
  284. /**
  285. * Returns HTML for a date element formatted as a range.
  286. */
  287. function theme_date_display_range($variables) {
  288. $date1 = $variables['date1'];
  289. $date2 = $variables['date2'];
  290. $timezone = $variables['timezone'];
  291. $attributes_start = $variables['attributes_start'];
  292. $attributes_end = $variables['attributes_end'];
  293. $start_date = '<span class="date-display-start"' . drupal_attributes($attributes_start) . '>' . $date1 . '</span>';
  294. $end_date = '<span class="date-display-end"' . drupal_attributes($attributes_end) . '>' . $date2 . $timezone . '</span>';
  295. // If microdata attributes for the start date property have been passed in,
  296. // add the microdata in meta tags.
  297. if (!empty($variables['add_microdata'])) {
  298. $start_date .= '<meta' . drupal_attributes($variables['microdata']['value']['#attributes']) . '/>';
  299. $end_date .= '<meta' . drupal_attributes($variables['microdata']['value2']['#attributes']) . '/>';
  300. }
  301. // Wrap the result with the attributes.
  302. return t('!start-date to !end-date', array(
  303. '!start-date' => $start_date,
  304. '!end-date' => $end_date,
  305. ));
  306. }
  307. /**
  308. * Returns HTML for a date element formatted as an interval.
  309. */
  310. function theme_date_display_interval($variables) {
  311. $entity = $variables['entity'];
  312. $options = $variables['display']['settings'];
  313. $dates = $variables['dates'];
  314. $attributes = $variables['attributes'];
  315. // Get the formatter settings, either the default settings for this node type
  316. // or the View settings stored in $entity->date_info.
  317. if (!empty($entity->date_info) && !empty($entity->date_info->formatter_settings)) {
  318. $options = $entity->date_info->formatter_settings;
  319. }
  320. $time_ago_vars = array(
  321. 'start_date' => $dates['value']['local']['object'],
  322. 'end_date' => $dates['value2']['local']['object'],
  323. 'interval' => $options['interval'],
  324. 'interval_display' => $options['interval_display'],
  325. );
  326. if ($return = theme('date_time_ago', $time_ago_vars)) {
  327. return '<span class="date-display-interval"' . drupal_attributes($attributes) . ">$return</span>";
  328. }
  329. else {
  330. return '';
  331. }
  332. }
  333. /**
  334. * Returns HTML for a start/end date combination on form.
  335. */
  336. function theme_date_combo($variables) {
  337. $element = $variables['element'];
  338. $field = field_info_field($element['#field_name']);
  339. $instance = field_info_instance($element['#entity_type'], $element['#field_name'], $element['#bundle']);
  340. // Group start/end items together in fieldset.
  341. $fieldset = array(
  342. '#title' => field_filter_xss(t($element['#title'])) . ' ' . ($element['#delta'] > 0 ? intval($element['#delta'] + 1) : ''),
  343. '#value' => '',
  344. '#description' => !empty($element['#fieldset_description']) ? $element['#fieldset_description'] : '',
  345. '#attributes' => array(),
  346. '#children' => $element['#children'],
  347. );
  348. // Add marker to required date fields.
  349. if ($element['#required']) {
  350. $fieldset['#title'] .= " " . theme('form_required_marker');
  351. }
  352. return theme('fieldset', array('element' => $fieldset));
  353. }
  354. /**
  355. * Returns HTML for the text/select options for date parts in a table.
  356. */
  357. function theme_date_text_parts($variables) {
  358. $element = $variables['element'];
  359. $rows = array();
  360. foreach (date_granularity_names() as $key => $part) {
  361. if ($element[$key]['#type'] == 'hidden') {
  362. $rows[] = drupal_render($element[$key]);
  363. }
  364. else {
  365. $rows[] = array($part, drupal_render($element[$key][0]), drupal_render($element[$key][1]));
  366. }
  367. }
  368. if ($element['year']['#type'] == 'hidden') {
  369. return implode($rows) . drupal_render_children($element);
  370. }
  371. else {
  372. $header = array(t('Date part'), t('Select list'), t('Text field'));
  373. return theme('table', array('header' => $header, 'rows' => $rows)) . drupal_render_children($element);
  374. }
  375. }
  376. /** @} End of addtogroup themeable */