View source
<?php
define('DIMENSION_MODE_LENGTH', 1);
define('DIMENSION_MODE_AREA', 2);
define('DIMENSION_MODE_VOLUME', 3);
define('DIMENSION_DATATYPE_INTEGER', 1);
define('DIMENSION_DATATYPE_DECIMAL', 2);
function dimension_field_info() {
return array(
'dimension' => array(
'label' => t('Dimensions'),
'description' => t('This field stores length or area (width/height) or volume (width/height/depth).'),
'settings' => _dimension_default_field_instance_settings(),
'default_widget' => 'dimension_widget',
'default_formatter' => 'dimension_formatter',
'property_type' => 'dimension',
'property_callbacks' => array(
'dimension_field_dimension_property_callback',
),
),
);
}
function dimension_field_dimension_property_callback(&$info, $entity_type, $field, $instance, $field_type) {
$property =& $info[$entity_type]['bundles'][$instance['bundle']]['properties'][$field['field_name']];
$property['getter callback'] = 'entity_metadata_field_verbatim_get';
$property['setter callback'] = 'entity_metadata_field_verbatim_set';
unset($property['query callback']);
list($has_length, $has_more) = _dimension_get_modes($field['settings']['mode']);
if ($has_length) {
$property['property info']['length'] = array(
'type' => 'integer',
'label' => t('Length'),
'setter callback' => 'entity_property_verbatim_set',
);
}
if ($has_more) {
$property['property info']['width'] = array(
'type' => 'integer',
'label' => t('Width'),
'setter callback' => 'entity_property_verbatim_set',
);
$property['property info']['height'] = array(
'type' => 'integer',
'label' => t('Height'),
'setter callback' => 'entity_property_verbatim_set',
);
}
}
function dimension_field_formatter_info() {
return array(
'dimension_formatter' => array(
'label' => t('Dimensions as table'),
'description' => t('Display the dimensions as a table.'),
'field types' => array(
'dimension',
),
),
'dimension_formatter_simple' => array(
'label' => t('Dimensions as simple line'),
'description' => t('Display the dimensions as a single line.'),
'field types' => array(
'dimension',
),
),
);
}
function dimension_field_widget_info() {
return array(
'dimension_widget' => array(
'label' => t('Dimension Widget'),
'description' => t('TODO.'),
'field types' => array(
'dimension',
),
),
);
}
function dimension_field_settings_form($field, $instance, $has_data) {
$settings = $field['settings'];
$form['mode'] = array(
'#type' => 'select',
'#title' => t('Dimensions'),
'#options' => dimension_get_modes_select(),
'#default_value' => $settings['mode'],
);
return $form;
}
function dimension_field_instance_settings_form($field, $instance) {
$settings = drupal_array_merge_deep(_dimension_default_field_instance_settings(), $instance['settings']);
list($has_length, $has_more) = _dimension_get_modes($field['settings']['mode']);
$field_names = array(
'height',
'width',
'length',
);
$columns = array(
'label',
'prefix',
'suffix',
'datatype',
'decimals',
'factor',
'descr',
);
$form['#tree'] = TRUE;
$form['fields'] = array(
'#type' => 'container',
'#prefix' => '<table><tr>
<th>' . t('Dimension') . '</th>
<th>' . t('Label') . '</th>
<th>' . t('Prefix') . '</th>
<th>' . t('Suffix') . '</th>
<th>' . t('Data type') . '</th>
<th>' . t('Decimals') . '</th>
<th>' . t('Factor') . '</th>
<th>' . t('Description') . '</th>
</tr>',
'#suffix' => '</table>',
);
$n = 0;
foreach ($field_names as $field_name) {
$n++;
$form['fields'][$field_name] = array(
'#type' => 'container',
'#prefix' => '<tr><td>' . t('Dimension %n', array(
'%n' => $n,
)) . '</td>',
'#suffix' => '</tr>',
'#access' => $field_name == 'length' ? $has_length : $has_more,
);
foreach ($columns as $column) {
if ($column == 'datatype') {
$form['fields'][$field_name][$column] = array(
'#type' => 'select',
'#default_value' => $settings['fields'][$field_name][$column],
'#options' => array(
DIMENSION_DATATYPE_INTEGER => t('Integer'),
DIMENSION_DATATYPE_DECIMAL => t('Decimal'),
),
'#prefix' => '<td>',
'#suffix' => '</td>',
);
}
else {
$form['fields'][$field_name][$column] = array(
'#type' => 'textfield',
'#default_value' => $settings['fields'][$field_name][$column],
'#size' => 6,
'#prefix' => '<td>',
'#suffix' => '</td>',
);
}
}
}
if ($has_more) {
$form['dimension_unit'] = array(
'#type' => 'textfield',
'#title' => t('Unit for the !name', array(
'!name' => $has_length ? t('volume') : t('area'),
)),
'#default_value' => empty($settings['dimension_unit']) ? '' : $settings['dimension_unit'],
'#size' => 6,
);
}
return $form;
}
function dimension_field_validate($entity_type, $entity, $field, $instance, $langcode, $items, &$errors) {
if (empty($field)) {
return;
}
$settings = $instance['settings'];
list($has_length, $has_more) = _dimension_get_modes($field['settings']['mode']);
$field_names = $has_length ? array(
'length',
) : array();
$field_names += $has_more ? array(
'height',
'width',
) : array();
foreach ($items as $delta => $item) {
foreach ($field_names as $field_name) {
$value = trim($item[$field_name]);
$field_settings = $settings['fields'][$field_name];
switch ($field_settings['datatype']) {
case DIMENSION_DATATYPE_INTEGER:
if (strval((int) $value) !== $value) {
$errors[$instance['field_name']][$langcode][$delta][] = array(
'error' => 'Dimension requires an integer value',
'message' => t('The value for %label needs to be an integer.', array(
'%label' => $field_settings['label'],
)),
);
}
break;
case DIMENSION_DATATYPE_DECIMAL:
if (strval((double) $value) !== $value) {
$errors[$instance['field_name']][$langcode][$delta][] = array(
'error' => 'Dimension requires a decimal value',
'message' => t('The value for %label needs to be an decimal.', array(
'%label' => $field_settings['label'],
)),
);
}
break;
default:
break;
}
if ($value <= 0) {
$errors[$instance['field_name']][$langcode][$delta][] = array(
'error' => 'Dimension with negative value',
'message' => t('The value for %label needs to be positive.', array(
'%label' => $field_settings['label'],
)),
);
}
}
}
}
function dimension_field_widget_form(&$form, &$form_state, $field, $instance, $langcode, $items, $delta, $element) {
$settings = $instance['settings'];
list($has_length, $has_more) = _dimension_get_modes($field['settings']['mode']);
$item = isset($items[$delta]) ? $items[$delta] : array();
$dimensions = array();
_dimension_field_widget_form_field($dimensions, 'length', $has_length, $item, $settings);
_dimension_field_widget_form_field($dimensions, 'width', $has_more, $item, $settings);
_dimension_field_widget_form_field($dimensions, 'height', $has_more, $item, $settings);
$element['#type'] = 'fieldset';
$element += $dimensions;
return $element;
}
function dimension_field_formatter_view($entity_type, $entity, $field, $instance, $langcode, $items, $display) {
$element = array();
$settings = $instance['settings'];
switch ($display['type']) {
case 'dimension_formatter':
foreach ($items as $delta => $item) {
$element[$delta] = array(
'#theme' => 'dimension_theme_table',
'#mode' => $field['settings']['mode'],
'#item' => $item,
'#settings' => $settings,
);
}
break;
case 'dimension_formatter_simple':
foreach ($items as $delta => $item) {
$element[$delta] = array(
'#theme' => 'dimension_theme_simple',
'#mode' => $field['settings']['mode'],
'#item' => $item,
'#settings' => $settings,
);
}
break;
}
return $element;
}
function dimension_field_is_empty($item, $field) {
return FALSE;
}
function dimension_theme($existing, $type, $theme, $path) {
return array(
'dimension_theme_table' => array(
'variables' => array(
'mode' => DIMENSION_MODE_LENGTH,
'item' => array(),
'settings' => array(),
),
),
'dimension_theme_simple' => array(
'variables' => array(
'mode' => DIMENSION_MODE_LENGTH,
'item' => array(),
'settings' => array(),
),
),
'dimension_theme_value' => array(
'variables' => array(
'value' => array(),
'settings' => array(),
'label' => TRUE,
),
),
);
}
function theme_dimension_theme_value($variable) {
$value = $variable['value'];
$settings = $variable['settings'];
$container = $variable['label'] ? 'div' : 'span';
$output = '<' . $container . ' class="dimension">';
if ($variable['label']) {
$output .= '<span class="label">' . $settings['label'] . ':</span>';
}
$output .= '<span class="value">' . $settings['prefix'] . $value . $settings['suffix'] . '</span>';
$output .= '</' . $container . '>';
return $output;
}
function theme_dimension_theme_table($variable) {
$mode = $variable['mode'];
$item = $variable['item'];
$settings = $variable['settings'];
list($has_length, $has_more) = _dimension_get_modes($mode);
$output = '<div class="dimension dimension-table">';
if ($has_length) {
$output .= theme('dimension_theme_value', array(
'value' => $item['length'],
'settings' => $settings['fields']['length'],
));
}
if ($has_more) {
$output .= theme('dimension_theme_value', array(
'value' => $item['width'],
'settings' => $settings['fields']['width'],
));
$output .= theme('dimension_theme_value', array(
'value' => $item['height'],
'settings' => $settings['fields']['height'],
));
}
if ($has_more && !empty($settings['dimension_unit'])) {
$label = $has_length ? t('Volume') : t('Area');
$class = $has_length ? 'volume' : 'area';
$dimension = dimension_calculate($item, $settings['fields']);
$output .= '<div class="dimension ' . $class . '"><span class="label">' . $label . ':</span><span class="value">' . $dimension . $settings['dimension_unit'] . '</span></div>';
}
$output .= '</div>';
drupal_add_css(drupal_get_path('module', 'dimension') . '/dimension.css');
return $output;
}
function theme_dimension_theme_simple($variable) {
$mode = $variable['mode'];
$item = $variable['item'];
$settings = $variable['settings'];
list($has_length, $has_more) = _dimension_get_modes($mode);
$output = '<div class="dimension dimension-simple">';
$labels = array();
$values = array();
if ($has_length) {
$labels[] = substr($settings['fields']['length']['label'], 0, 1);
$values[] = theme('dimension_theme_value', array(
'value' => $item['length'],
'settings' => $settings['fields']['length'],
'label' => FALSE,
));
}
if ($has_more) {
$labels[] = substr($settings['fields']['width']['label'], 0, 1);
$values[] = theme('dimension_theme_value', array(
'value' => $item['width'],
'settings' => $settings['fields']['height'],
'label' => FALSE,
));
$labels[] = substr($settings['fields']['height']['label'], 0, 1);
$values[] = theme('dimension_theme_value', array(
'value' => $item['height'],
'settings' => $settings['fields']['height'],
'label' => FALSE,
));
}
$output .= '<span class="label">' . implode('/', $labels) . ':</span>';
$output .= '<span class="value">' . implode('/', $values) . '</span>';
if ($has_more && !empty($settings['dimension_unit'])) {
$label = $has_length ? t('Volume') : t('Area');
$class = $has_length ? 'volume' : 'area';
$dimension = dimension_calculate($item, $settings['fields']);
$output .= '<span class="dimension ' . $class . '"><span class="label">' . $label . ':</span><span class="value">' . $dimension . $settings['dimension_unit'] . '</span></span>';
}
$output .= '</div>';
drupal_add_css(drupal_get_path('module', 'dimension') . '/dimension.css');
return $output;
}
function dimension_calculate($dimensions, $settings) {
$length = (isset($dimensions['length']) ? $dimensions['length'] : 1) * $settings['length']['factor'];
$height = (isset($dimensions['height']) ? $dimensions['height'] : 1) * $settings['height']['factor'];
$width = (isset($dimensions['width']) ? $dimensions['width'] : 1) * $settings['width']['factor'];
return $length * $width * $height;
}
function dimension_get_modes_select() {
return array(
DIMENSION_MODE_LENGTH => t('Length'),
DIMENSION_MODE_AREA => t('Width and Height'),
DIMENSION_MODE_VOLUME => t('Width, Height and Depth'),
);
}
function _dimension_get_modes($mode) {
$has_length = in_array($mode, array(
DIMENSION_MODE_LENGTH,
DIMENSION_MODE_VOLUME,
));
$has_more = in_array($mode, array(
DIMENSION_MODE_AREA,
DIMENSION_MODE_VOLUME,
));
return array(
$has_length,
$has_more,
);
}
function _dimension_default_field_instance_settings() {
return array(
'mode' => DIMENSION_MODE_LENGTH,
'fields' => array(
'length' => array(
'label' => t('Length'),
'prefix' => '',
'suffix' => 'mm',
'descr' => '',
'datatype' => DIMENSION_DATATYPE_INTEGER,
'decimals' => 0,
'factor' => 1,
),
'height' => array(
'label' => t('Height'),
'prefix' => '',
'suffix' => 'mm',
'descr' => '',
'datatype' => DIMENSION_DATATYPE_INTEGER,
'decimals' => 0,
'factor' => 1,
),
'width' => array(
'label' => t('Width'),
'prefix' => '',
'suffix' => 'mm',
'descr' => '',
'datatype' => DIMENSION_DATATYPE_INTEGER,
'decimals' => 0,
'factor' => 1,
),
),
);
}
function _dimension_field_widget_form_field(&$form_fields, $name, $access, $item, $settings) {
$settings = drupal_array_merge_deep(_dimension_default_field_instance_settings(), $settings);
$field_settings = $settings['fields'][$name];
$form_fields[$name] = array(
'#type' => 'textfield',
'#title' => $field_settings['label'],
'#field_prefix' => $field_settings['prefix'],
'#field_suffix' => $field_settings['suffix'],
'#description' => $field_settings['descr'],
'#default_value' => isset($item[$name]) ? $item[$name] : 1,
'#size' => 6,
'#access' => $access,
);
}