Выводим десятичные величины как градусы, минуты и секунды дуги

Главные вкладки

Аватар пользователя direqtor direqtor 7 августа 2008 в 11:02

Вывод значений числоых полей CCK в виде градусной меры посредством пользовательской темизации вывода поля.

Итак, если вам захотелось действительное числовое значение (с целой и дробной частью) поля CCK вывести в виде градусов, минут и секунд, то нет ничего проще.

Создадим в любом типе данных числовое поле CCK.
Field type: Float
Назовем его, например degree, а его системное имя будет field_degree.
Заголовок: Градусы.
Widget type: Text field.
Остальные настройки оставим по умолчанию.
На вкладке «Manage fields» Установим поле сразу под заголовком. На вкладке «Display fields» выберем для отображения формат 9999.

Создадим материал указанного типа. Заполним заголовок, в поле «Градусы» добавим произвольное действительное значение, например: 123.456. Сохраним материал. Ничего необычного. На странице под заголовком появилась надпись «Градусы:» под ней 123, дробная часть обрезана, поскольку мы выбрали для отображения целочисленный формат.

А теперь попробуем отобразить наше поле в материале как-нибудь по другому, например в виде градусов, минут и секунд дуги: 123°27'22". Сделать это можно написав собственную функцию темизации вывода значений этого поля.

Чтобы найти нужную нам функцию, откроем файл модуля number.module (находится в подпапке modules/number модуля CCK), который в CCK отвечает за вывод, редактирование и хранение числовых данных.

Найдем там хук number_field_formatter_info(). Найдем там элемент массива с 'label' => '9999' – именно этот формат мы выбрали, его и будем темизировать в нашем поле. Его имя "default". Найдем в файле хук number_theme(), где описаны функции темизирующие вывод числовых полей. Требуемый нам ключ "number_formatter_default", а функция темизации должна называться theme_number_formatter_default().
Поскольку в элементе массива с этим ключом есть элемент "function" со значением "theme_number_formatter_generic", то Drupal будет использовать ее. Но найденное имя number_formatter_default тоже потребуется нам, чтобы передать работу системы темизации пользовательской функции. Для ее написания воспользуемся кодом функции theme_number_formatter_generic(). Приведу его полностью (Drupal 6).

function theme_number_formatter_generic($element) {
  $field = content_fields($element['#field_name'], $element['#type_name']);
  $value = $element['#item']['value'];

  if (($allowed_values = content_allowed_values($field))) {
    if (isset($allowed_values[$value]) && $allowed_values[$value] != $value) {
      return $allowed_values[$value];
    }
  }
  switch ($element['#formatter']) {
    case 'us_0':
      $output = number_format($value, 0, '.', ',');
      break;
    case 'us_1':
      $output = number_format($value, 1, '.', ',');
      break;
    case 'us_2':
      $output = number_format($value, 2, '.', ',');
      break;
    case 'be_0':
      $output = number_format($value, 0, ',', '.');
      break;
    case 'be_1':
      $output = number_format($value, 1, ',', '.');
      break;
    case 'be_2':
      $output = number_format($value, 2, ',', '.');
      break;
    case 'fr_0':
      $output = number_format($value, 0, ', ', ' ');
      break;
    case 'fr_1':
      $output = number_format($value, 1, ', ', ' ');
      break;
    case 'fr_2':
      $output = number_format($value, 2, ', ', ' ');
      break;
    default:
      $output = $value;
      break;
  }
  $prefixes = isset($field['prefix']) ? explode('|', check_plain($field['prefix'])) : array(0 => '');
  $suffixes = isset($field['suffix']) ? explode('|', check_plain($field['suffix'])) : array(0 => '');
  $prefix = (count($prefixes) > 1) ? format_plural($value, $prefixes[0], $prefixes[1]) : $prefixes[0];
  $suffix = (count($suffixes) > 1) ? format_plural($value, $suffixes[0], $suffixes[1]) : $suffixes[0];
  return $prefix . $output . $suffix;
}

Видно, что она применяется для всех форматов вывода поля. Но нам потребуется только секция default в операторе switch поскольку мы выбрали для темизации только этот формат. Кроме того, нам потребуется название поля которое мы темизируем (field_degree). Во всех остальных случаях, мы восстановим нормальную обработку значений поля. Оставим также и префиксы с суффиксами. А вот вывод значения поля изменим.

Откроем в папке используемой темы файл template.php или создадим его, если отсутствует. Добавим в него код нашей пользовательской функции для темизации вывода значений поля field_degree.

/*
  Системное имя функции темизации theme_number_formatter_default(), хотя на самом деле вызывается другая функция,
  но нам придется использовать это имя и назвать нашу функцию phptemplate_number_formatter_default()
  Она и будет вызвана вместо theme_number_formatter_generic()
*/

function phptemplate_number_formatter_default ($element) {
/*
  Этот параметр показывает сколько знаков после запятой мы выведем в секундах дуги
  0 - секунды дуги выводятся как целое число
*/

$second_round = 1;
/*
  Проверяем имя поля, поступившего в функцию.
  Если оно не field_degree, то вызываем функцию, которая используется в модуле number
*/

  if ($element["#field_name"]!="field_degree") return theme_number_formatter_generic($element);
/*
 Здесь идет код из функции theme_number_formatter_generic()
*/

  $field = content_fields($element['#field_name'], $element['#type_name']);
  $value = $element['#item']['value'];
  if (($allowed_values = content_allowed_values($field))) {
    if (isset($allowed_values[$value]) && $allowed_values[$value] != $value) {
      return $allowed_values[$value];
    }
  }
/*
  Здесь мы превращаем действительное число в строковую запись градусной величины
  с учетом требуемой точности. Поскольку Drupal поддерживает UTF-8 вместо °
  можно использовать сам значок градуса ° взятый из таблицы символов или
  набранный как Alt+0176. Для знака минут дуги применяется одиночная кавычка,
  для знака секунд – двойная.
*/
 
  $degrees = intval($value);
  $rest = ($value > 0 ? $value - $degrees : $degrees - $value)*60;
  $minutes = intval ($rest);
  $rest = ($rest - $minutes)*60;
  $seconds = round($rest, $second_round);
  $output = $degrees . '°' . ($seconds ? (str_pad($minutes, 2, '0', STR_PAD_LEFT) . "'" . str_pad($seconds, 2, '0', STR_PAD_LEFT) . '"') : ($minutes ? str_pad($minutes, 2, '0', STR_PAD_LEFT) . "'" : ''));
/*
 Здесь идет завершающий код из функции theme_number_formatter_generic()
*/

  $prefixes = isset($field['prefix']) ? explode('|', check_plain($field['prefix'])) : array(0 => '');
  $suffixes = isset($field['suffix']) ? explode('|', check_plain($field['suffix'])) : array(0 => '');
  $prefix = (count($prefixes) > 1) ? format_plural($value, $prefixes[0], $prefixes[1]) : $prefixes[0];
  $suffix = (count($suffixes) > 1) ? format_plural($value, $suffixes[0], $suffixes[1]) : $suffixes[0];
  return $prefix . $output . $suffix;
}

Сохраняем файл template.php, выключаем используемую нами тему, включаем снова и обновляем недавно созданную страницу. Теперь значение поля должно выглядеть так:

Градусы:
123°27'21.6"

Удобство способа в том, что не затронут код исходного модуля.

Источники

Статья в блоге автора

Content Construction Kit (CCK)

Комментарии

Аватар пользователя Ромка Ромка 7 августа 2008 в 13:25

Quote:
выключаем используемую нами тему, включаем снова

Вот это делать не обязательно. Для того чтобы очистить theme registry нужно или просто в списке тем нажать кнопку "Сохранить" или очистить кэш в меню "Perfomance" ("Administer > Site configuration > Performance").

Аватар пользователя neochief neochief 8 августа 2008 в 4:00

Внутри кода второй функции следует поменять вызов на theme('number_formatter_generic',$element)

HTML код минут (′) — ′ или ′
Секунд (″) — ″ или ″

Плюс, нарушены некоторые стандарты кодирования Друпала, а именно Control Structures (у вас — условные блоки), ну и по мелочам — пробелы, то да се. Модуль coder очень облегчит вам задачу.

А в остальном — супер. Написано достойно.

Аватар пользователя gfedin gfedin 16 июля 2009 в 16:22

Помогите и начинающим! Пожста!!

Есть модуль Computed Field, он предназначен для сложения вычитания Умножения и т.д. полей

Подскажите как выводить в нужном формате результат например умножения.

там есть Формат вывода материалов:

<?phpdisplay = $node_field_item['value'];?>

что нужно дописать чтоб выводился результат в формате например us_2