matrix.module in Matrix field 6
Same filename and directory in other branches
Defines simple matrix field types.
File
matrix.moduleView source
<?php
/**
* @file
* Defines simple matrix field types.
*/
/**
* Implementation of hook_field_info().
*/
function matrix_field_info() {
return array(
'matrix' => array(
'label' => t('Matrix Field'),
'description' => t('Creates a grid of form fields.'),
),
);
}
/**
* Implementation of hook_field_settings().
*/
function matrix_field_settings($op, $field) {
switch ($op) {
case 'form':
$form = array();
$form['size'] = array(
'#type' => 'textfield',
'#size' => 5,
'#title' => t('Size of textfields'),
'#default_value' => !empty($field['size']) ? $field['size'] : 5,
);
$form['rows'] = array(
'#type' => 'textarea',
'#title' => t('Headers in Row'),
'#default_value' => $currfield['extra']['questions'],
'#description' => t('List down left side headers. One per line.') . '<br />',
'#cols' => 60,
'#rows' => 5,
'#weight' => -2,
'#required' => TRUE,
'#default_value' => isset($field["rows"]) ? $field["rows"] : '',
);
$form['cols'] = array(
'#type' => 'textarea',
'#title' => t("Headers in Column"),
'#default_value' => $currfield['extra']['questions'],
'#description' => t('List down top row headers. One per line.') . '<br />',
'#cols' => 60,
'#rows' => 5,
'#weight' => -2,
'#required' => TRUE,
'#default_value' => isset($field["cols"]) ? $field["cols"] : '',
);
return $form;
case 'save':
$values[] = 'rows';
$values[] = 'cols';
$values[] = 'size';
return $values;
}
}
/**
* Implementation of hook_content_is_empty().
* Since this module does not allow multiple values, this function serves no purpose.
*/
function matrix_content_is_empty($item, $field) {
return FALSE;
}
/**
* Implementation of hook_field().
*/
function matrix_field($op, &$node, $field, &$items, $teaser, $page) {
$rows = trim($field['rows']);
$cols = trim($field['cols']);
$rows = explode("\n", $rows);
$cols = explode("\n", $cols);
switch ($op) {
case 'load':
$result = db_query("SELECT value, row, col FROM {node_field_matrix_data} WHERE vid = %d AND field_name = '%s'", $node->vid, $field['field_name']);
$values = array();
while ($data = db_fetch_object($result)) {
$values['data'][$data->row][$data->col] = $data->value;
}
$values['rows_header'] = $rows;
$values['cols_header'] = $cols;
$additions = array(
$field['field_name'] => $values,
);
return $additions;
case 'update':
db_query("DELETE FROM {node_field_matrix_data} WHERE vid = %d and field_name= '%s'", $node->vid, $field['field_name']);
case 'update':
case 'insert':
$i = 0;
foreach ($rows as $row) {
if ($row) {
$j = 0;
foreach ($cols as $col) {
if ($col) {
db_query("INSERT INTO {node_field_matrix_data} (nid, vid, field_name, row, col, value)\n VALUES (%d, %d, '%s', %d, %d, '%s')", $node->nid, $node->vid, $field['field_name'], $i, $j, $items[0][$i][$j]);
$j++;
}
}
$i++;
}
}
break;
}
}
/**
* Implementation of hook_widget_info().
*/
function matrix_widget_info() {
return array(
'matrix' => array(
'label' => 'Text fields in a matrix form',
'field types' => array(
'matrix',
),
'multiple values' => CONTENT_HANDLE_CORE,
),
);
}
/**
* Implementation of hook_widget().
*/
function matrix_widget(&$form, &$form_state, $field, $items, $delta = 0) {
$element = array(
'#type' => $field['widget']['type'],
'#default_value' => $items['data'],
);
return $element;
}
/**
* Implementation of hook_theme().
*/
function matrix_theme() {
return array(
'matrix_field_settings' => array(
'arguments' => array(
'element' => NULL,
),
),
'matrix_formatter_default' => array(
'arguments' => array(
'element' => NULL,
),
),
'matrix_table_form' => array(
'arguments' => array(
'form' => NULL,
),
),
);
}
/**
* Theme the matrix elements into a table
*/
function theme_matrix_table_form($form) {
$rows = array();
$header = $form['header']['#value'];
foreach ($form as $row_key => $fields) {
if (!empty($form['first_col']['#value'][$row_key])) {
$row = array();
$row[] = $form['first_col']['#value'][$row_key];
foreach ($fields as $col_key => $field) {
if ($field['#type'] == 'textfield') {
$row[] = drupal_render($form[$row_key][$col_key]);
}
}
$rows[] = $row;
}
}
drupal_render($form['header']);
drupal_render($form['first_col']);
$output = drupal_render($form);
$output .= '<div id="edit-' . $form['#field_name'] . '-wrapper">';
$output .= '<label>' . $form['#title'] . ': </label>';
$output .= theme('table', $header, $rows, array(
'class' => 'matrix',
));
$output .= '<div class="description">' . $form['#description'] . '</div>';
$output .= '</div>';
return $output;
}
/**
* Implementation of hook_elements().
*/
function matrix_elements() {
$elements['matrix'] = array(
'#input' => TRUE,
'#columns' => array(
'data',
),
'#process' => array(
'matrix_process',
),
);
return $elements;
}
/**
* Process the matrix type element before displaying the field.
*
* Build the form element. When creating a form using FAPI #process,
* note that $element['#value'] is already set.
*
* The $fields array is in $form['#field_info'][$element['#field_name']].
*/
function matrix_process($element, $edit, $form_state, $form) {
$field = $form['#field_info'][$element['#field_name']];
if ($field['rows'] && $field['cols']) {
$rows = trim($field['rows']);
$cols = trim($field['cols']);
$rows = explode("\n", $rows);
$cols = explode("\n", $cols);
}
$processed_element = array(
'#tree' => TRUE,
'#weight' => $field['widget']['weight'],
'#theme' => 'matrix_table_form',
'#prefix' => '<div class="form-item matrix_field">',
'#suffix' => '</div>',
'#parents' => $element['#parents'],
'#title' => $element['#title'],
'#description' => $element['#description'],
'#required' => $element['#required'],
'#field_name' => $element['#field_name'],
'#type_name' => $element['#type_name'],
'#delta' => $element['#delta'],
'#columns' => $element['#columns'],
);
if ($cols) {
$header = array_merge(array(
'',
), $cols);
}
$first_col = $rows;
$rows = (array) $rows;
$i = 0;
foreach ($rows as $row) {
if ($row) {
$j = 0;
foreach ($cols as $col) {
if ($col) {
$processed_element[$i][$j] = array(
'#type' => 'textfield',
'#size' => $field['size'],
'#default_value' => isset($edit[$i][$j]) ? $edit[$i][$j] : $element['#default_value'][$i][$j],
'#attributes' => array(
'class' => "matrix-column-{$i} matrix-row-{$j} matrix-cell-{$i}-{$j}",
),
);
$j++;
}
}
$i++;
}
}
$processed_element['header'] = array(
'#value' => $header,
);
$processed_element['first_col'] = array(
'#value' => $first_col,
);
return $processed_element;
}
/**
* Implementation of hook_field_formatter_info().
*/
function matrix_field_formatter_info() {
return array(
'default' => array(
'label' => t('Data grid (default)'),
'field types' => array(
'matrix',
),
),
);
}
/**
* Theme function for 'default' text field formatter.
* This gets called for each row, but we only want to render all the data at once
* so we use a staticly cached variable to ignore subsquent calls.
* @param $element The whole $node object, but containing specific information relating to the delta of this element.
* @return HTML.
*/
function theme_matrix_formatter_default($element) {
$field_info = $element['#node']->{$element}['#field_name'];
if (!is_array($field_info['cols_header']) || !is_array($field_info['data'])) {
return;
}
$header = $field_info['cols_header'];
// Translatable headers
foreach ($header as $i => $h) {
$header[$i] = t($h);
}
array_unshift($header, '');
static $rendered;
//since we are rendering the whole thing in one go, we don't want to rerender for each fow
$nid = $element['#node']->nid;
if ($rendered[$nid][$element['#field_name']] != TRUE) {
$rendered[$nid][$element['#field_name']] = TRUE;
//replace blank cells with a dash
ksort($field_info['data']);
foreach ($field_info['data'] as $row_index => $row) {
ksort($row);
foreach ($row as $cell_index => $cell_value) {
if ($cell_value == '') {
$data[$row_index][$cell_index] = '<span class="matrix-row-' . $row_index . ' matrix-column-' . $cell_index . ' matrix-cell-' . $row_index . '-' . $cell_index . '">' . '-' . '</span>';
}
else {
$data[$row_index][$cell_index] = '<span class="matrix-row-' . $row_index . ' matrix-column-' . $cell_index . ' matrix-cell-' . $row_index . '-' . $cell_index . '">' . $cell_value . '</span>';
$show_row = $row_index;
$has_data = TRUE;
//this is used to hide the whole display if no data is entered what so ever.
}
}
$row_label = '<b>' . array_shift($field_info['rows_header']) . '</b>';
array_unshift($data[$row_index], $row_label);
}
//add blank cells if the number of rows/columns is different to the number of headers
//this can happen when columns/rows are added to an existing content type
$row_count = count($data[0]);
if ($row_count < count($header)) {
for ($i = $row_count; $i < count($header); $i++) {
for ($j = 0; $j < count($data); $j++) {
$data[$j][$i] = '<span class="matrix-row-' . $j . ' matrix-column-' . $i . ' matrix-cell-' . $j . '-' . $i . '">' . '-' . '</span>';
}
}
}
//strip out rows at the end of the dataset where there is no data
foreach ($data as $row_id => $row) {
if ($row_id <= $show_row) {
$flushed_data[] = $row;
}
}
if ($has_data) {
return theme('table', $header, $flushed_data);
}
else {
return '';
}
}
}
/**
* Implmentation of hook_form_alter()
*
* Disable the multiple values settings. This module won't work with them.
*/
function matrix_form_alter(&$form, $form_state, $form_id) {
if ($form_id == 'content_field_edit_form' && $form['#field']['type'] == 'matrix') {
$form['field']['multiple']['#type'] = 'hidden';
//hide the multiple values form. It does not work with this module!
}
}
Functions
Name![]() |
Description |
---|---|
matrix_content_is_empty | Implementation of hook_content_is_empty(). Since this module does not allow multiple values, this function serves no purpose. |
matrix_elements | Implementation of hook_elements(). |
matrix_field | Implementation of hook_field(). |
matrix_field_formatter_info | Implementation of hook_field_formatter_info(). |
matrix_field_info | Implementation of hook_field_info(). |
matrix_field_settings | Implementation of hook_field_settings(). |
matrix_form_alter | Implmentation of hook_form_alter() |
matrix_process | Process the matrix type element before displaying the field. |
matrix_theme | Implementation of hook_theme(). |
matrix_widget | Implementation of hook_widget(). |
matrix_widget_info | Implementation of hook_widget_info(). |
theme_matrix_formatter_default | Theme function for 'default' text field formatter. This gets called for each row, but we only want to render all the data at once so we use a staticly cached variable to ignore subsquent calls. |
theme_matrix_table_form | Theme the matrix elements into a table |