Setting the Thousands Seperator in Drupal 7
The other day I ran into a small problem with manipulating a field in Drupal 7. Specifically, I had a field represent the number of minutes that a task took and had modified my template to display it as a combination of hours and minutes.
The code I had was pretty simple as you can imagine
$min = intval($minutes); $minutesAndHours = new stdClass(); $minutesAndHours->hours = intval(floor($min/60)); //avoid floats $minutesAndHours->minutes = abs($min - ($minutesAndHours->hours*60)); $minutesAndHours->minutesLabel = $minutesAndHours->minutes == 1 ? 'Minute' : 'Minutes'; $minutesAndHours->hoursLabel = $minutesAndHours->hours > 1 ? 'Hours' : ( $minutesAndHours->hours == 1 && $minutesAndHours->minutes > 0 ? 'Hours' : 'Hour'); $minutesAndHours->formatted = sprintf('%1$d:%2$02d', $minutesAndHours->hours, $minutesAndHours->minutes);
Nothing too exciting here, as it's all pretty normal stuff. On the first line
the use of intval converts strings like
"123" into integers
123. As any
C programmer will know, intval reads as much of a string as it can and converts
it into an integer. This can often lead to some funny things if you're not being
mindful of the format of the string:
php > print intval('123'); 123 php > print intval(' 123'); 123 php > print intval(' 123 '); 123 php > print intval(' 1 2 3 '); 1 php > print intval(' 12a34 '); 12
Whitespace will be consumed from the left with no problem, however once a non-numeric character is found the conversion breaks early. This leads to the results of the last two examples above.
Drupal has a lot of formatters out of the box and they're easy to manage from the menus within the Content Type -> Type -> Manage Displays admin. One of the configuration option is the thousands placeholder. Back in 2011 it was noted that it'd be better to have an empty space for a default than a space. However, as pointed out by a comment
"changing the default will never affect any existing fields on the site because they will have already had their settings saved to the database"
Combined with poor defaults on the field_view_field, the aged site I was working on sent out the number of minutes to my function with a space seperating the thousands place. My attempts to modify this via the admin menu were, expectedly, met with 0 results. So I began looking into the function I was using: field_view_value.
This function takes a few parameters. An entity type (in this case
$node, the name of the field you'd like to retrieve, and an item which
can be retrieved by
field_get_items's first element. Optionally, it also takes
display array and language code. As hinted at by the comment, we need to
send along our own display array to retrieve the format we want.
Determining what to send as the array is the major issue I had. A few of the
fields are documented, but the
settings array was far less so. The mentioned
hook_field_formatter_info didn't have anything about a list of possible formats
or what to pass to Drupal to get what I wanted. So it was up to me to hunt.
For about 10 minutes or so I scoured the Drupal api documentation, followed links, opened 70 tabs and bothered duckduckgo and google about the issue. Finally, I decided that the best way to figure it out was to rely on the fact that the Drupal developers probably named the admin fields with the same nested arrays they seem to love to abuse in their code.
I wasn't dissappointed:
Once I found this is was trivial to add in the appropriate array to my call to
field_view_value and get the expected result back:
$fields = field_get_items('node', $node, $val); $value = field_view_value('node', $node, $val, $fields, array( 'label' => 'inline', 'type' => 'default_formatter', 'settings' => array('thousand_separator' => '' ) ) );
So when in doubt with Drupal settings or poorly documented lists of options, always check the source of the admin pages! You'll often find it helpful!