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

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

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


Revision 1.6 - (show annotations) (download) (as text)
Sun Oct 26 15:04:43 2008 UTC (13 months ago) by jpetso
Branch: MAIN
CVS Tags: DRUPAL-6--1-0, HEAD
Changes since 1.5: +2 -2 lines
File MIME type: text/x-php
#310833: Don't make the HMS format show up for nodes where the duration
         has not (yet) been entered.
1 <?php
2 // $Id: duration_api.module,v 1.5 2008/10/08 06:55:48 jpetso Exp $
3
4 /**
5 * @file
6 * An API to transform and perform evaluations on duration objects.
7 *
8 * This file contains supplemental functions which perform tasks that
9 * don't fit into the duration class itself. Formatting, mostly.
10 *
11 * Copyright 2007, 2008 by Jakob Petsovits <jpetso@gmx.at>
12 * Distributed under the GNU General Public Licence version 2 or higher,
13 * as published by the FSF on http://www.gnu.org/copyleft/gpl.html
14 */
15
16 // The nice stuff mostly concerns the Duration object.
17 include_once(drupal_get_path('module', 'duration') .'/duration.inc');
18
19
20 /**
21 * Format a duration object as simple list of values with their metric name,
22 * delimited by a comma (or another delimiter that you might specify).
23 * Zero values will not be included.
24 *
25 * @param $duration
26 * The duration object that should be formatted as string.
27 * @param $delimiter
28 * The string that separates the formatted values. The default comma should
29 * be fine for many cases, but you can just as well use delimiters like
30 * ' | ', '\</li\>\<li\>' or even ' ' and '' (those especially make sense if
31 * you use functions like 'duration_metric_hms' as @p $format_callback).
32 * @param $format_callback
33 * The function that provides a single formatted metric string.
34 * It takes the two arguments $metric and $value and should return a string
35 * including the value and the metric name (or an empty string - in that case
36 * this metric won't be included in the resulting list).
37 * @param $display_callback
38 * The function that determines which values will be shown and which are
39 * filtered out from the list. It takes a single argument, $duration_values,
40 * which contains all metrics (as array keys) and their values (as array
41 * values). That array is already sorted in the same way that it will show up
42 * in the formatted output. The function should return another structured
43 * array with again metrics as array keys and the "display state" as values:
44 * TRUE if this value should be displayed, or FALSE if it shouldn't.
45 * @param $sort
46 * The order of the list: 'descending' for "years first, seconds last",
47 * and 'ascending' for "seconds first, years last".
48 */
49 function duration_format_list($duration, $delimiter = ', ', $format_callback = 'duration_metric_plural', $display_callback = 'duration_display_nonzero', $sort = 'descending') {
50 if (!is_object($duration) || !$duration->is_valid()) {
51 return '';
52 }
53 $strings = array();
54 $duration_values = $duration->to_array($sort);
55 $display = $display_callback($duration_values);
56
57 // If all values are filtered out, let's still display at least one of them.
58 $display_true = array_filter($display);
59 if (empty($display_true)) {
60 $display['seconds'] = TRUE;
61 }
62
63 // Now that this is sorted out, let's get down to business!
64 foreach ($duration_values as $metric => $value) {
65 if (!$display[$metric]) {
66 continue; // the filter says we should not display this value
67 }
68 $strings[] = $format_callback($metric, $value);
69 }
70 return implode($delimiter, $strings);
71 }
72
73 /**
74 * Convenience function to render a duration object in the '23h0m15s' format.
75 * Years, months, weeks and days will be (approximately) broken down so they
76 * fit into the hours/minutes/seconds scheme.
77 */
78 function duration_format_hms($duration, $delimiter = '') {
79 if (!is_object($duration) || !$duration->is_valid()) {
80 return '';
81 }
82 $duration = clone($duration); // let's not modify the original object, mmkay?
83 $duration->set_granularity('seconds', 'hours');
84 return duration_format_list($duration, $delimiter,
85 'duration_metric_hms', 'duration_display_connected', 'descending'
86 );
87 }
88
89 /**
90 * Display callback for duration_format_list():
91 * Specify all values to be displayed, regardless of their values.
92 */
93 function duration_display_all($duration_values) {
94 $display = array();
95 foreach ($duration_values as $metric => $value) {
96 $display[$metric] = TRUE;
97 }
98 return $display;
99 }
100
101 /**
102 * Display callback for duration_format_list():
103 * Specify all zero values to be filtered out.
104 */
105 function duration_display_nonzero($duration_values) {
106 $display = array();
107 foreach ($duration_values as $metric => $value) {
108 $display[$metric] = ($value != 0); // TRUE for non-zero, FALSE for zero values
109 }
110 return $display;
111 }
112
113 /**
114 * Display callback for duration_format_list():
115 * Exclude values above the largest non-zero metric and below the smallest one.
116 */
117 function duration_display_connected($duration_values) {
118 $display = array();
119 $encountered_nonzero_value = FALSE;
120
121 // First run: Set values above the largest non-zero metric to FALSE,
122 // and remember the smallest non-zero metric.
123 foreach ($duration_values as $metric => $value) {
124 if ($encountered_nonzero_value) {
125 if ($value != 0) {
126 $smallest_nonzero_metric = $metric; // save for later processing
127 }
128 }
129 else { // did not yet encounter a non-zero value
130 if ($value == 0) {
131 $display[$metric] = FALSE; // still no luck... try the next one
132 continue;
133 }
134 $encountered_nonzero_value = TRUE; // yay, non-zero - let's display this value
135 $smallest_nonzero_metric = $metric;
136 }
137 $display[$metric] = TRUE; // enable displaying this unless we think it over
138 }
139 // Second run: Now that we know the smallest non-zero metric,
140 // filter out the values below that one.
141 $filter = FALSE;
142 foreach ($duration_values as $metric => $value) {
143 if ($filter) {
144 $display[$metric] = FALSE;
145 }
146 if ($metric == $smallest_nonzero_metric) {
147 $filter = TRUE; // from the next value on, filter to our hearts' content
148 }
149 }
150 return $display;
151 }
152
153
154 /**
155 * Return a structured array of possible metric identifier strings.
156 * Note that unless you specify the duration @p $type, both 'months'
157 * and 'weeks' are included, but only one of those can exist in a duration.
158 * Take care on that issue.
159 *
160 * @param $type
161 * If you specify 'months' or 'weeks' instead of the default value NULL,
162 * the other one of those two will be left out as month and week format
163 * is mutually exclusive. In other words, with @p $type == 'months' you'll
164 * get no 'weeks' in the result array, and with @p $type == 'weeks' there
165 * won't be 'months' in there.
166 * @param $sort
167 * The order of the metrics in the result value:
168 * - 'descending' for "years first, seconds last"
169 * - 'ascending' for "seconds first, years last".
170 */
171 function duration_metrics($type = NULL, $sort = 'descending') {
172 $metrics = array(
173 'years', 'months', 'weeks', 'days',
174 'hours', 'minutes', 'seconds',
175 );
176 if (isset($type)) {
177 $removed_key = ($type == 'months')
178 ? array_search('weeks', $metrics)
179 : array_search('months', $metrics);
180 unset($metrics[$removed_key]);
181 }
182 if ($sort == 'ascending') {
183 $metrics = array_reverse($metrics);
184 }
185 return $metrics;
186 }
187
188 /**
189 * Translate a metric idendifier string to a user visible string.
190 * Use this only for displaying the plain metrics names - if you want to
191 * display value/metric pairs like "18 years" then you want to use
192 * duration_metric_plural() instead.
193 */
194 function duration_metric_t($metric) {
195 static $metrics; // cache that stuff
196
197 if (!isset($metrics)) {
198 $metrics = array(
199 'years' => t('years'),
200 'months' => t('months'),
201 'weeks' => t('weeks'),
202 'days' => t('days'),
203 'hours' => t('hours'),
204 'minutes' => t('minutes'),
205 'seconds' => t('seconds'),
206 );
207 }
208 return $metrics[$metric];
209 }
210
211 /**
212 * Translate a duration value and metric with format_plural.
213 */
214 function duration_metric_plural($metric, $value) {
215 $metrics = array(
216 'seconds' => array(
217 'singular' => t('1 second'),
218 'plural' => t('@count seconds'),
219 ),
220 'minutes' => array(
221 'singular' => t('1 minute'),
222 'plural' => t('@count minutes'),
223 ),
224 'hours' => array(
225 'singular' => t('1 hour'),
226 'plural' => t('@count hours'),
227 ),
228 'days' => array(
229 'singular' => t('1 day'),
230 'plural' => t('@count days'),
231 ),
232 'weeks' => array(
233 'singular' => t('1 week'),
234 'plural' => t('@count weeks'),
235 ),
236 'months' => array(
237 'singular' => t('1 month'),
238 'plural' => t('@count months'),
239 ),
240 'years' => array(
241 'singular' => t('1 year'),
242 'plural' => t('@count years'),
243 ),
244 );
245 return format_plural($value, $metrics[$metric]['singular'], $metrics[$metric]['plural']);
246 }
247
248 /**
249 * Suffix the given value with a short (untranslated) metrics identifier, e.g.
250 * the arguments 'seconds' and 1 make '1s', or 'years' and 2008 make '2008y'.
251 */
252 function duration_metric_hms($metric, $value) {
253 static $metrics; // cache that stuff
254
255 if (!isset($metrics)) {
256 $metrics = array(
257 'seconds' => 's',
258 'minutes' => 'm',
259 'hours' => 'h',
260 'days' => 'd',
261 'weeks' => 'w',
262 'months' => 'mon',
263 'years' => 'y',
264 );
265 }
266 return $value . $metrics[$metric];
267 }
268
269
270 /**
271 * Format the values of a duration object in a user specified format.
272 *
273 * @param $duration
274 * The duration object to be formatted.
275 * @param $format
276 * The format that will be used. You can use the following placeholders:
277 * - %y - number of years (e.g. '1', '10000').
278 * - %m - number of months, without padding (e.g. '1', '12').
279 * - %o - number of months, padded to two digits (e.g. '01', '12').
280 * - %v - number of weeks, without padding (e.g. '1', '52').
281 * - %V - number of weeks, padded to two digits (e.g. '01', '52').
282 * - %e - number of days, without padding (e.g. '1', '31').
283 * - %d - number of days, padded to two digits (e.g. '01', '31').
284 * - %h - number of hours, without padding (e.g. '1', '24').
285 * - %H - number of hours, padded to two digits (e.g. '01', '24').
286 * - %O - number of minutes, without padding (e.g. '1', '60').
287 * - %M - number of minutes, padded to two digits (e.g. '01', '60').
288 * - %s - number of seconds, without padding (e.g. '1', '60').
289 * - %S - number of seconds, padded to two digits (e.g. '01', '60').
290 * - %n - newline character.
291 * - %% - a literal '%' character.
292 */
293 function duration_format_custom($duration, $format = '%h:%M:%S') {
294 if (!is_object($duration) || !$duration->is_valid()) {
295 return '';
296 }
297 $replacements = array(
298 '%y' => strval($duration->get_years()),
299 '%m' => strval($duration->get_months()),
300 '%o' => _duration_pad($duration->get_months()),
301 '%v' => strval($duration->get_weeks()),
302 '%V' => _duration_pad($duration->get_weeks()),
303 '%e' => strval($duration->get_days()),
304 '%d' => _duration_pad($duration->get_days()),
305 '%h' => strval($duration->get_hours()),
306 '%H' => _duration_pad($duration->get_hours()),
307 '%O' => strval($duration->get_minutes()),
308 '%M' => _duration_pad($duration->get_minutes()),
309 '%s' => strval($duration->get_seconds()),
310 '%S' => _duration_pad($duration->get_seconds()),
311 '%n' => "\n",
312 '%%' => '%',
313 );
314 return strtr($format, $replacements);
315 }
316
317 /**
318 * Specialized padding function, using '0' as (left) pad and taking
319 * potential decimal points into account for the calculation of the actual
320 * pad length.
321 */
322 function _duration_pad($number, $pad_length = 2) {
323 $number_string = strval($number);
324 $found = strpos($number_string, '.');
325 if ($found !== FALSE) {
326 $pad_length = strlen($number_string) - $found + $pad_length;
327 }
328 return str_pad($number_string, $pad_length, '0', STR_PAD_LEFT);
329 }

  ViewVC Help
Powered by ViewVC 1.1.2