/[drupal]/contributions/modules/duration/duration.module
ViewVC logotype

Contents of /contributions/modules/duration/duration.module

Parent Directory Parent Directory | Revision Log Revision Log | View Revision Graph Revision Graph


Revision 1.12 - (show annotations) (download) (as text)
Wed Oct 8 06:36:24 2008 UTC (13 months, 2 weeks ago) by jpetso
Branch: MAIN
CVS Tags: DRUPAL-6--1-0-RC2, DRUPAL-6--1-0, HEAD
Changes since 1.11: +32 -1 lines
File MIME type: text/x-php
Make formatters work in views by providing a custom field handler
that loads the Duration object (which CCK's default handler does not).
1 <?php
2 // $Id: duration.module,v 1.11 2008/07/17 17:25:47 jpetso Exp $
3
4 /**
5 * @file
6 * A CCK field for entering time durations.
7 *
8 * Copyright 2008 by Jakob Petsovits <jpetso@gmx.at>
9 * Distributed under the GNU General Public Licence version 2 or higher,
10 * as published by the FSF on http://www.gnu.org/copyleft/gpl.html
11 */
12
13
14 /**
15 * Implementation of hook_field_info().
16 */
17 function duration_field_info() {
18 return array(
19 'duration' => array(
20 'label' => t('Duration'),
21 'description' => t('Store a duration in the database as an ISO duration.'),
22 ),
23 );
24 }
25
26 /**
27 * Implementation of hook_field_settings().
28 */
29 function duration_field_settings($op, $field) {
30 switch ($op) {
31 case 'form':
32 $form = array();
33 return $form;
34
35 case 'save':
36 return array();
37
38 case 'database columns':
39 return array(
40 'iso8601' => array(
41 'type' => 'varchar',
42 'length' => '64',
43 'not null' => TRUE,
44 'default' => '',
45 ),
46 'approx_seconds' => array(
47 'type' => 'int',
48 'unsigned' => TRUE,
49 'not null' => TRUE,
50 'default' => 0,
51 'sortable' => TRUE,
52 ),
53 );
54
55 case 'views data':
56 $data = content_views_field_views_data($field);
57 $db_info = content_database_info($field);
58 $table_alias = content_views_tablename($field);
59
60 // Set our own field handler so that loads the Duration object (like in
61 // hook_field($op='load')), because CCK's standard field handler doesn't
62 // do that.
63 $data[$table_alias][$field['field_name'] .'_iso8601']['field']['handler'] = 'duration_handler_field';
64
65 return $data;
66 }
67 }
68
69 /**
70 * Implementation of hook_field().
71 */
72 function duration_field($op, &$node, $field, &$items, $teaser, $page) {
73 switch ($op) {
74 case 'load':
75 // Add a third property in addition to 'iso8601' and 'approx_seconds':
76 // 'duration', containing the duration object for the ISO string.
77 foreach ($items as $delta => $item) {
78 $items[$delta]['duration'] = duration_create($item['iso8601']);
79 }
80 return array($field['field_name'] => $items);
81 }
82 }
83
84 /**
85 * Implementation of hook_content_is_empty().
86 */
87 function duration_content_is_empty($item, $field) {
88 if (empty($item['iso8601'])) {
89 return TRUE;
90 }
91 return FALSE;
92 }
93
94
95 /**
96 * Implementation of hook_field_formatter_info().
97 */
98 function duration_field_formatter_info() {
99 return array(
100 'default' => array(
101 'label' => t('List of metrics ("2 months, 15 days, ...")'),
102 'field types' => array('duration'),
103 'multiple values' => CONTENT_HANDLE_CORE,
104 ),
105 'hms' => array(
106 'label' => t('HMS ("3h20m45s")'),
107 'field types' => array('duration'),
108 'multiple values' => CONTENT_HANDLE_CORE,
109 ),
110 'colons' => array(
111 'label' => t('Time with colons ("3:20:45")'),
112 'field types' => array('duration'),
113 'multiple values' => CONTENT_HANDLE_CORE,
114 ),
115 );
116 }
117
118 /**
119 * Implementation of hook_theme().
120 */
121 function duration_theme() {
122 return array(
123 'duration_formatter_default' => array(
124 'arguments' => array('element' => NULL),
125 ),
126 'duration_formatter_hms' => array(
127 'arguments' => array('element' => NULL),
128 ),
129 'duration_formatter_colons' => array(
130 'arguments' => array('element' => NULL),
131 ),
132 );
133 }
134
135 /**
136 * Theme function for the 'default' duration field formatter.
137 */
138 function theme_duration_formatter_default($element) {
139 if (isset($element['#node']->duration)) { // loaded by duration_handler_field
140 $element['#item']['duration'] = $element['#node']->duration;
141 }
142 return duration_format_list($element['#item']['duration']);
143 }
144
145 /**
146 * Theme function for the 'hms' duration field formatter.
147 */
148 function theme_duration_formatter_hms($element) {
149 if (isset($element['#node']->duration)) { // loaded by duration_handler_field
150 $element['#item']['duration'] = $element['#node']->duration;
151 }
152 return duration_format_hms($element['#item']['duration']);
153 }
154
155 /**
156 * Theme function for the 'colons' duration field formatter.
157 */
158 function theme_duration_formatter_colons($element) {
159 if (isset($element['#node']->duration)) { // loaded by duration_handler_field
160 $element['#item']['duration'] = $element['#node']->duration;
161 }
162 return duration_format_custom($element['#item']['duration'], '%h:%M:%S');
163 }
164
165
166 /**
167 * Implementation of hook_widget_info().
168 */
169 function duration_widget_info() {
170 return array(
171 'duration_combo' => array(
172 'label' => t('Text Fields'),
173 'field types' => array('duration'),
174 'multiple values' => CONTENT_HANDLE_CORE,
175 ),
176 );
177 }
178
179 /**
180 * Implementation of hook_widget_settings().
181 */
182 function duration_widget_settings($op, $widget) {
183 switch ($op) {
184 case 'form':
185 $form = array();
186
187 if ($widget['type'] == 'duration_combo') {
188 $form['use_weeks'] = array(
189 '#type' => 'checkbox',
190 '#title' => t('Use weeks instead of months'),
191 '#description' => t('The date part of a duration can either be specified using one of the (mutually exclusive) formats "years/months/days" or "years/weeks/days". By default, the former one is used, but you can switch to the weeks format by checking this option.'),
192 '#default_value' => isset($widget['use_weeks']) ? $widget['use_weeks'] : 0,
193 '#required' => TRUE,
194 );
195
196 $metrics = duration_metrics('months');
197 $metric_options = array();
198 foreach ($metrics as $metric) {
199 if ($metric == 'months') {
200 $metric_options[$metric] = t('!months/!weeks', array(
201 '!months' => duration_metric_t('months'),
202 '!weeks' => duration_metric_t('weeks'),
203 ));
204 }
205 else {
206 $metric_options[$metric] = duration_metric_t($metric);
207 }
208 }
209
210 $form['largest_metric'] = array(
211 '#type' => 'select',
212 '#title' => t('Largest metric that can be entered'),
213 '#options' => $metric_options,
214 '#default_value' => $widget['largest_metric']
215 ? $widget['largest_metric']
216 : 'years',
217 '#required' => TRUE,
218 );
219 $form['smallest_metric'] = array(
220 '#type' => 'select',
221 '#title' => t('Smallest metric that can be entered'),
222 '#options' => $metric_options,
223 '#default_value' => $widget['smallest_metric']
224 ? $widget['smallest_metric']
225 : 'seconds',
226 '#required' => TRUE,
227 );
228 }
229 else { // not a duration combo, assign arbitrary default values instead.
230 $form['use_weeks'] = array('#type' => 'hidden', '#value' => 0);
231 $form['largest_metric'] = array('#type' => 'hidden', '#value' => 'years');
232 $form['smallest_metric'] = array('#type' => 'hidden', '#value' => 'seconds');
233 }
234 return $form;
235
236 case 'validate':
237 // Make sure the smallest metric is at least as small as the largest metric.
238 $metrics = duration_metrics('months', 'descending');
239 foreach ($metrics as $metric) {
240 if ($metric == $widget['largest_metric']) {
241 // Encountered the lartest metric first, that's how it should be.
242 break;
243 }
244 if ($metric == $widget['smallest_metric']) {
245 // Encountered the smallest metric first, which means it's larger
246 // than the largest metric. That can't be allowed, obviously.
247 form_set_error('smallest_metric',
248 t('The "smallest metric" must not be greater than the "largest metric".')
249 );
250 }
251 }
252 break;
253
254 case 'save':
255 return array('use_weeks', 'largest_metric', 'smallest_metric');
256 }
257 }
258
259 /**
260 * Implementation of hook_widget().
261 */
262 function duration_widget(&$form, &$form_state, $field, $items, $delta = 0) {
263 if ($field['widget']['type'] == 'duration_combo') {
264 // If we're using weeks format, make sure everything complies to that.
265 if ($field['widget']['use_weeks']) {
266 if ($field['widget']['largest_metric'] == 'months') {
267 $field['widget']['largest_metric'] = 'weeks';
268 }
269 if ($field['widget']['smallest_metric'] == 'months') {
270 $field['widget']['smallest_metric'] = 'weeks';
271 }
272 if (isset($items[$delta]['duration'])) {
273 $items[$delta]['duration']->set_type('weeks');
274 }
275 else {
276 $items[$delta]['duration'] = duration_create('P0W');
277 }
278 }
279 $element = array(
280 '#type' => 'duration_combo',
281 '#default_value' => isset($items[$delta]['duration'])
282 ? $items[$delta]['duration']
283 : NULL,
284 '#largest_metric' => isset($field['widget']['largest_metric'])
285 ? $field['widget']['largest_metric']
286 : 'years',
287 '#smallest_metric' => isset($field['widget']['smallest_metric'])
288 ? $field['widget']['smallest_metric']
289 : 'seconds',
290 '#element_validate' => array('duration_combo_validate'),
291 );
292 }
293 return $element;
294 }
295
296 /**
297 * Additional 'validate' callback for 'duration_combo' widgets.
298 * Transforms the original element form value to the CCK item (array) format.
299 */
300 function duration_combo_validate($element, &$form_state) {
301 $item = array(
302 'duration' => $element['#value'],
303 'iso8601' => $element['#value']->to_iso(),
304 'approx_seconds' => $element['#value']->to_single_metric('seconds'),
305 );
306 form_set_value($element, $item, $form_state);
307 }
308
309
310 /**
311 * Implementation of hook_menu().
312 */
313 function duration_menu() {
314 $items['duration-cck'] = array(
315 'title' => 'Duration CCK field test form',
316 'page callback' => 'drupal_get_form',
317 'page arguments' => array('duration_test_form'),
318 'access arguments' => array('access content'),
319 'type' => MENU_CALLBACK,
320 );
321 return $items;
322 }
323
324 /**
325 * Implementation of hook_views_api().
326 */
327 function duration_views_api() {
328 return array(
329 'api' => 2.0,
330 'path' => drupal_get_path('module', 'duration') . '/views',
331 );
332 }

  ViewVC Help
Powered by ViewVC 1.1.2