values.module in Values 6
Same filename and directory in other branches
API for managing reusable value sets.
File
values.moduleView source
<?php
/**
* @file
* API for managing reusable value sets.
*/
/**
* Implementation of hook_perm().
*/
function values_perm() {
return array(
'administer values',
);
}
/**
* Implementation of hook_menu().
*/
function values_menu() {
$items = array();
$items['admin/content/values'] = array(
'title' => 'Values',
'description' => 'Manage reusable value lists.',
'page callback' => 'values_list',
'access arguments' => array(
'administer values',
),
);
$items['admin/content/values/list'] = array(
'title' => 'List',
'page callback' => 'values_list',
'access arguments' => array(
'administer values',
),
'weight' => -10,
'type' => MENU_DEFAULT_LOCAL_TASK,
);
$items['admin/content/values/add'] = array(
'title' => 'Add',
'page callback' => 'drupal_get_form',
'page arguments' => array(
'values_form',
'add',
),
'access arguments' => array(
'administer values',
),
'weight' => -9,
'type' => MENU_LOCAL_TASK,
);
$items['admin/content/values/import'] = array(
'title' => 'Import',
'page callback' => 'drupal_get_form',
'page arguments' => array(
'values_import_form',
),
'access arguments' => array(
'administer values',
),
'weight' => -8,
'type' => MENU_LOCAL_TASK,
);
$items['admin/content/values/%values'] = array(
'title' => 'Values',
'page callback' => 'drupal_get_form',
'page arguments' => array(
'values_form',
'edit',
3,
),
'access arguments' => array(
'administer values',
),
'type' => MENU_CALLBACK,
);
$items['admin/content/values/%values/edit'] = array(
'title' => 'Edit',
'page callback' => 'drupal_get_form',
'page arguments' => array(
'values_form',
'edit',
3,
),
'access arguments' => array(
'administer values',
),
'weight' => -9,
'type' => MENU_DEFAULT_LOCAL_TASK,
);
$items['admin/content/values/%values/delete'] = array(
'title' => 'Delete',
'page callback' => 'drupal_get_form',
'page arguments' => array(
'values_delete_confirm',
3,
),
'access arguments' => array(
'administer values',
),
'weight' => -8,
'type' => MENU_LOCAL_TASK,
);
$items['admin/content/values/%values/export'] = array(
'title' => 'Export',
'page callback' => 'drupal_get_form',
'page arguments' => array(
'values_export_values',
3,
),
'access arguments' => array(
'administer values',
),
'weight' => -7,
'type' => MENU_LOCAL_TASK,
);
$items['values/js'] = array(
'title' => 'Javascript Values Form',
'page callback' => 'values_form_js',
'access arguments' => array(
'administer values',
),
'type' => MENU_CALLBACK,
);
return $items;
}
/**
* Displays a list of existing value sets.
*/
function values_list() {
if (module_exists('ctools')) {
ctools_include('export');
}
$header = array(
t('Description'),
t('Storage'),
array(
'data' => t('Operations'),
'colspan' => 2,
),
);
$rows = array();
// Get all the configured value sets and create a nice table
$values_lists = values_load_all();
foreach ($values_lists as $values) {
// Determine database delete operation
switch ($values->export_type) {
case EXPORT_IN_CODE:
$db_delete = FALSE;
break;
case EXPORT_IN_CODE | EXPORT_IN_DATABASE:
$db_delete = t('revert');
break;
case EXPORT_IN_DATABASE:
default:
$db_delete = t('delete');
break;
}
// Create table row for display
$rows[] = array(
$values->description,
$values->type ? $values->type : t('Normal'),
l(t('edit'), 'admin/content/values/' . $values->name . '/edit'),
$db_delete ? l($db_delete, 'admin/content/values/' . $values->name . '/delete') : '',
);
}
return theme_table($header, $rows);
}
/**
* Form for adding a new value set.
*/
function values_form(&$form_state, $action = 'edit', $values = NULL) {
if ($form_state['values_count']) {
$values->data = $form_state['values']['data'];
}
else {
$values = values_load($values, TRUE);
}
$form = array();
$form['action'] = array(
'#type' => 'value',
'#value' => $action,
);
// Don't change machine names if we're editing a set
if (isset($values->name)) {
$form['name'] = array(
'#type' => 'hidden',
'#value' => $values->name,
);
}
$form['description'] = array(
'#type' => 'textfield',
'#title' => t('Value set description'),
'#description' => t('This description will appear on the administrative table to tell you what the values are about.'),
'#default_value' => $values ? $values->description : '',
'#required' => TRUE,
'#weight' => -9,
);
// Count values
if (isset($form_state['values_count'])) {
$values_count = $form_state['values_count'];
}
else {
$values_count = max(2, empty($values->data) ? 2 : count($values->data));
}
// Wrapper for values
$form['values_wrapper'] = array(
'#tree' => FALSE,
'#title' => t('Values'),
'#description' => t('These are the actual values associated with this value set.'),
'#prefix' => '<div class="clear-block" id="values-value-wrapper">',
'#suffix' => '</div>',
'#weight' => -8,
);
// Container for value fields
$form['values_wrapper']['data'] = array(
'#tree' => TRUE,
'#prefix' => '<div id="values-values">',
'#suffix' => '</div>',
'#theme' => 'values_value_fields',
'#cache' => TRUE,
);
// Add the current values to the form.
for ($delta = 0; $delta < $values_count; $delta++) {
$form['values_wrapper']['data'][$delta] = array(
'value' => array(
'#type' => 'textfield',
'#title' => t('Value @n', array(
'@n' => $delta + 1,
)),
'#default_value' => isset($values->data[$delta]['value']) ? $values->data[$delta]['value'] : '',
'#size' => 4,
'#maxlength' => 32,
),
'label' => array(
'#type' => 'textfield',
'#title' => t('Label for value @n', array(
'@n' => $delta + 1,
)),
'#default_value' => isset($values->data[$delta]['label']) ? $values->data[$delta]['label'] : '',
'#access' => user_access('administer values'),
),
'weight' => array(
'#type' => 'weight',
'#delta' => $values_count,
'#default_value' => isset($values->data[$delta]['weight']) ? intval($values->data[$delta]['weight']) : $delta,
),
);
}
// AHAH-enabled "Add more" button
$form['values_wrapper']['values_add_more'] = array(
'#type' => 'submit',
'#value' => t('Add more'),
'#description' => t("If the amount of options above isn't enough, click here to add more."),
'#weight' => 1,
'#submit' => array(
'values_add_more_submit',
),
// If no javascript action.
'#ahah' => array(
'path' => 'values/js',
'wrapper' => 'values-values',
'method' => 'replace',
'effect' => 'fade',
),
);
$form['submit'] = array(
'#type' => 'submit',
'#value' => t('Save'),
'#weight' => 10,
);
return $form;
}
/**
* Submit handler to add more values to a value set. This handler is used when
* javascript is not available. It makes changes to the form state and the
* entire form is rebuilt during the page reload.
*/
function values_add_more_submit($form, &$form_state) {
// Make the changes we want to the form state.
if ($form_state['values']['values_add_more']) {
$n = $_GET['q'] == 'values/js' ? 1 : 5;
$form_state['values_count'] = count($form_state['values']['data']) + $n;
}
}
/**
* Menu callback for AHAH additions.
*/
function values_form_js() {
$form_state = array(
'storage' => NULL,
'submitted' => FALSE,
);
$form_build_id = $_POST['form_build_id'];
// Get the form from the cache.
$form = form_get_cache($form_build_id, $form_state);
$args = $form['#parameters'];
$form_id = array_shift($args);
// We will run some of the submit handlers so we need to disable redirecting.
$form['#redirect'] = FALSE;
// We need to process the form, prepare for that by setting a few internals
// variables.
$form['#post'] = $_POST;
$form['#programmed'] = FALSE;
$form_state['post'] = $_POST;
// Build, validate and if possible, submit the form.
drupal_process_form($form_id, $form, $form_state);
// This call recreates the form relying solely on the form_state that the
// drupal_process_form set up.
$form = drupal_rebuild_form($form_id, $form_state, $args, $form_build_id);
// Render the new output.
$values_form = $form['values_wrapper']['data'];
// Prevent duplicate wrappers.
unset($values_form['#prefix'], $values_form['#suffix']);
$output = theme('status_messages') . drupal_render($values_form);
drupal_json(array(
'status' => TRUE,
'data' => $output,
));
}
/**
* Validates the values form.
*/
function values_form_validate(&$form, &$form_state) {
// Values name must be unique
if ($form_state['values']['action'] == 'add') {
$machine_name = values_machine_name($form_state['values']['description']);
$values = values_load($machine_name);
if ($values) {
form_set_error('name', t('You must use a unique name for this value set.'));
}
}
}
/**
* Submits the values form.
*/
function values_form_submit(&$form, &$form_state) {
$values = new stdClass();
$values->name = !isset($form_state['values']['name']) ? values_machine_name($form_state['values']['description']) : $form_state['values']['name'];
$values->description = $form_state['values']['description'];
$values->data = array();
foreach ($form_state['values']['data'] as $value) {
$values->data[] = array(
'value' => $value['value'],
'label' => $value['label'],
'weight' => $value['weight'],
);
}
values_save($values);
$form_state['redirect'] = 'admin/content/values';
}
/**
* Automatically generate a machine name for the values object.
*/
function values_machine_name($description) {
$machine_name = trim(preg_replace('/[^a-z0-9]+/', '_', strtolower($description)), '_');
return $machine_name;
}
/**
* Loads values object from the database.
*/
function values_load($name, $reset = FALSE) {
if (is_object($name)) {
$name = $name->name;
}
if (module_exists('ctools')) {
// Try using Chaos tools suite for exporting and caching
ctools_include('export');
$values = ctools_export_load_object('values_list', 'names', array(
$name,
));
}
else {
// In the absence of ctools, use our own basic static caching
static $values = array();
if ($reset || !isset($values[$name])) {
$values[$name] = db_fetch_object(db_query("SELECT * FROM {values_list} WHERE name = '%s'", $name));
if (isset($values[$name]->data)) {
$values[$name]->data = unserialize($values[$name]->data);
}
}
}
if ($name && isset($values[$name])) {
if (is_array($values[$name]->data)) {
usort($values[$name]->data, 'values_sort_by_weight');
}
return $values[$name];
}
return FALSE;
}
/**
* Sort list of values by weight.
*/
function values_sort_by_weight($a, $b) {
$a_weight = is_array($a) && isset($a['weight']) ? $a['weight'] : 0;
$b_weight = is_array($b) && isset($b['weight']) ? $b['weight'] : 0;
if ($a_weight == $b_weight) {
return 0;
}
return $a_weight < $b_weight ? -1 : 1;
}
/**
* Loads all value sets.
*/
function values_load_all() {
$values_sets = array();
if (module_exists('ctools')) {
// Try using Chaos tools suite for exporting and caching
ctools_include('export');
$values_sets = ctools_export_crud_load_all('values_list', TRUE);
asort($values_sets);
}
else {
$query = db_query('SELECT name FROM {values_list} ORDER BY description ASC');
while ($values = db_fetch_object($query)) {
$values_sets[] = values_load($values->name);
}
}
return $values_sets;
}
/**
* Saves a values object to the database.
*/
function values_save($values) {
// Delete existing values
values_delete($values->name);
// Create a new value set object
$set = new stdClass();
$set->name = $values->name;
$set->description = $values->description;
usort($values->data, 'values_sort_by_weight');
$set->data = $values->data;
// Write to the database
if ($success = drupal_write_record('values_list', $set)) {
drupal_set_message(t('Value set !name was saved.', array(
'!name' => '<em>' . $values->description . '</em>',
)));
}
}
/**
* Confirmation form to delete a value object from the database.
*/
function values_delete_confirm(&$form_state, $values) {
$form['name'] = array(
'#type' => 'value',
'#value' => $values->name,
);
$action = $values->export_type & EXPORT_IN_CODE ? 'revert' : 'delete';
$form['action'] = array(
'#type' => 'value',
'#value' => $action,
);
return confirm_form($form, t('Are you sure you want to !action !name?', array(
'!action' => $action,
'!name' => '<em>' . $values->description . '</em>',
)), 'admin/content/values', t('This action cannot be undone.'), t('!action', array(
'!action' => ucfirst($action),
)), t('Cancel'));
}
/**
* Calls deletion of a value object.
*/
function values_delete_confirm_submit(&$form, &$form_state) {
values_delete($form_state['values']['name']);
$action = $form_state['values']['action'] == 'delete' ? 'deleted' : 'reverted';
drupal_set_message(t('Value list was !action.', array(
'!action' => $action,
)));
$form_state['redirect'] = 'admin/content/values';
}
/**
* Deletes a value object from the database.
*/
function values_delete($name) {
if (is_object($name)) {
$name = $name->name;
}
db_query("DELETE FROM {values_list} WHERE name = '%s'", $name);
}
/**
* Implementation of hook_theme().
*/
function values_theme() {
return array(
'values_value_fields' => array(
'arguments' => array(
'form' => NULL,
),
),
);
}
/**
* Theme the admin values form.
*
* @ingroup themeable
*/
function theme_values_value_fields($form) {
// Define table headers
$headers = array(
t('Key'),
t('Label'),
t('Weight'),
);
// Build table rows
$rows = array();
foreach (element_children($form) as $key) {
// No need to print the field title every time
unset($form[$key]['value']['#title'], $form[$key]['label']['#title']);
$row = array();
$row[] = drupal_render($form[$key]['value']);
$row[] = drupal_render($form[$key]['label']);
$form[$key]['weight']['#attributes']['class'] = 'values-weight-group';
$row[] = drupal_render($form[$key]['weight']);
$rows[] = array(
'data' => $row,
'class' => 'draggable',
);
}
drupal_add_css(drupal_get_path('module', 'values') . '/values.css');
drupal_add_tabledrag('values-value-list', 'order', 'sibling', 'values-weight-group');
return theme('table', $headers, $rows, array(
'id' => 'values-value-list',
)) . drupal_render($form);
}
/**
* Export a value list and display it in a form.
*/
function values_export_values(&$form_state, $values) {
if (!module_exists('ctools')) {
return array(
'message' => array(
'#value' => t('For exporting capabilities, please install the !ctools module.', array(
'!ctools' => l('Chaos tools suite', 'http://drupal.org/project/ctools'),
)),
),
);
}
drupal_set_title(check_plain($values->description));
$code = values_export($values);
$lines = substr_count($code, "\n");
$form['export'] = array(
'#title' => t('Export data'),
'#type' => 'textarea',
'#value' => $code,
'#rows' => $lines,
'#description' => t('Copy the export text and paste it into another value list using the import function.'),
);
return $form;
}
/**
* Export a values list.
*/
function values_export($values, $indent = '') {
ctools_include('export');
$output = ctools_export_object('values_list', $values, $indent);
return $output;
}
/**
* Import a value list
*/
function values_import_form(&$form_state) {
drupal_set_message(t('Importing a value list with a conflicting name will override it.'), 'warning');
$form['import_type'] = array(
'#type' => 'radios',
'#title' => t('Import Type'),
'#options' => array(
'ctools' => 'Ctools Export',
'values' => 'key|value pairs',
),
'#default_value' => 'ctools',
);
$form['import'] = array(
'#type' => 'textarea',
'#title' => t('Import data'),
'#description' => t('Copy the text from an previously exported value list and paste it here.'),
'#default_value' => isset($form_state['values']['import']) ? $form_state['values']['import'] : '',
'#rows' => 10,
);
$form['import_values'] = array(
'#type' => 'fieldset',
'#title' => t('Import Values'),
'#description' => 'Import a new value set as a flat set of key|value pairs. Useful for migrating from allowed values lists to value sets.',
'#collapsible' => FALSE,
'#attributes' => array(
'id' => 'import-values-wrapper',
),
);
$form['import_values']['description'] = array(
'#type' => 'textfield',
'#title' => t('Value set description'),
'#description' => t('This description will appear on the administrative table to tell you what the values are about.'),
'#default_value' => '',
'#required' => TRUE,
);
// Wrapper for values
$form['import_values']['values'] = array(
'#type' => 'textarea',
'#title' => t('Import data'),
'#description' => t('Enter one value per line. Use the format key|value.'),
'#default_value' => '',
'#rows' => 10,
);
$form['submit'] = array(
'#type' => 'submit',
'#value' => t('Import'),
);
$form['#after_build'] = array(
'values_import_form_add_js',
);
return $form;
}
/**
* Submit function for value list import.
*/
function values_import_form_submit(&$form, &$form_state) {
if ($form_state['values']['import_type'] == 'values') {
$value_set = new stdClass();
$value_set->name = !isset($form_state['values']['name']) ? values_machine_name($form_state['values']['description']) : $form_state['values']['name'];
$value_set->description = $form_state['values']['description'];
// Process the key|value pairs
$list = explode("\n", $form_state['values']['values']);
$list = array_map('trim', $list);
$list = array_filter($list, 'strlen');
foreach ($list as $position => $text) {
$value_set->data[$position]['weight'] = $position;
// Check for an explicit key.
$matches = array();
if (preg_match('/(.*)\\|(.*)/', $text, $matches)) {
$value_set->data[$position]['value'] = $matches[1];
$value_set->data[$position]['label'] = $matches[2];
}
}
}
else {
$code = $form_state['values']['import'] . "\nreturn \$value_set;";
$value_set = eval($code);
}
values_save($value_set);
$form_state['redirect'] = 'admin/content/values/' . $value_set->name;
}
function values_import_form_add_js($form, &$form_state) {
drupal_add_js(drupal_get_path('module', 'values') . '/values.js');
return $form;
}
/**
* Implementation of hook_ctools_plugin_api().
*
* Tell CTools that we support the default_values_list API.
*/
function values_ctools_plugin_api($owner, $api) {
if ($owner == 'values' && $api == 'default_values_list') {
return array(
'version' => 1,
);
}
}
Functions
Name![]() |
Description |
---|---|
theme_values_value_fields | Theme the admin values form. |
values_add_more_submit | Submit handler to add more values to a value set. This handler is used when javascript is not available. It makes changes to the form state and the entire form is rebuilt during the page reload. |
values_ctools_plugin_api | Implementation of hook_ctools_plugin_api(). |
values_delete | Deletes a value object from the database. |
values_delete_confirm | Confirmation form to delete a value object from the database. |
values_delete_confirm_submit | Calls deletion of a value object. |
values_export | Export a values list. |
values_export_values | Export a value list and display it in a form. |
values_form | Form for adding a new value set. |
values_form_js | Menu callback for AHAH additions. |
values_form_submit | Submits the values form. |
values_form_validate | Validates the values form. |
values_import_form | Import a value list |
values_import_form_add_js | |
values_import_form_submit | Submit function for value list import. |
values_list | Displays a list of existing value sets. |
values_load | Loads values object from the database. |
values_load_all | Loads all value sets. |
values_machine_name | Automatically generate a machine name for the values object. |
values_menu | Implementation of hook_menu(). |
values_perm | Implementation of hook_perm(). |
values_save | Saves a values object to the database. |
values_sort_by_weight | Sort list of values by weight. |
values_theme | Implementation of hook_theme(). |