Headline'
$help = preg_replace('#^
=\s(.*?)
$#m', '$1
', $help);
// Make '*' bulleted list items into an HTML unordered list.
$help = preg_replace('#\*\s(.*?)
#s', '$1
', $help);
$help = preg_replace('##', '- ', $help, 1);
$help = strrev(preg_replace(strrev('#
#'), strrev('
'), strrev($help), 1));
return $help;
}
}
/**
* Implementation of hook_perm().
*/
function taxonomy_other_perm() {
return array('add other terms');
}
/**
* Implementation of hook_form_alter().
*/
function taxonomy_other_form_alter($form_id, &$form) {
if ($form_id == 'taxonomy_form_vocabulary') {
// Add new taxonomy_other vocabulary setting.
$form['taxonomy_other'] = array(
'#type' => 'checkbox',
'#title' => t('Users can add terms'),
'#default_value' => (int) in_array($form['vid']['#value'], variable_get('taxonomy_other_vids', array())),
'#description' => t('Allows users to add new terms. Adds \'- Other -\' to select lists.'),
);
// Add setting to hide taxonomy_other-created terms.
$form['taxonomy_other_show_terms'] = array(
'#type' => 'checkbox',
'#title' => t('Show user-added terms'),
'#default_value' => (int) in_array($form['vid']['#value'], variable_get('taxonomy_other_show_terms_vids', array())),
'#description' => t('Allows users to select terms added by other users.'),
);
// Sink 'weight', 'submit', 'delete' to the bottom of the settings.
$weight = 1;
foreach(array('weight', 'submit', 'delete') as $e) {
if (!isset($form[$e]['#weight'])) {
$form[$e]['#weight'] = $weight++;
}
}
// Register form callbacks.
$form['#validate']['taxonomy_other_taxonomy_form_vocabulary_validate'] = array();
$form['#submit']['taxonomy_other_taxonomy_form_vocabulary_submit'] = array();
}
// Alter node forms.
elseif ($form_id == $form['type']['#value'] . '_node_form') {
$new_fields = 0;
// For taxonomy vocabularies that use taxonomy_other...
foreach(variable_get('taxonomy_other_vids', array()) as $vid) {
// Vocabulary in use on this form?
if (isset($form['taxonomy'][$vid])) {
// Hide terms?
if (!in_array($vid, variable_get('taxonomy_other_show_terms_vids', array()))) {
$hide = array_flip(taxonomy_other_get_tids($vid));
if (isset($form['taxonomy'][$vid]['#default_value'][0])) {
unset($hide[$form['taxonomy'][$vid]['#default_value'][0]]);
}
// Remove the options from the select list.
foreach ($form['taxonomy'][$vid]['#options'] as $opt_key => $opt) {
if (is_object($opt) && isset($opt->option) && is_array($opt->option)) {
foreach (array_keys($opt->option) as $opt_tid) {
if (isset($hide[$opt_tid])) {
unset($form['taxonomy'][$vid]['#options'][$opt_key]);
}
}
}
}
}
// For users with permissions, add '- Other -' select option and a text field for a new term.
if (user_access('add other terms')) {
// Add the select option.
$form['taxonomy'][$vid]['#options'][] = (object) array('option' => array('taxonomy_other' => t('- Other -')));
// Add a specific weight for the select list, so we can make the text field follow immediately after.
$form['taxonomy'][$vid]['#weight'] = $form['taxonomy'][$vid]['#weight'] += 0.1 * $vid;
// Add the text field.
$form['taxonomy']['taxonomy_other_'. $vid] = array(
'#type' => 'textfield',
'#size' => 128,
'#title' => t('Other %title', array('%title' => $form['taxonomy'][$vid]['#title'])),
'#id' => 'taxonomy-other-'. $vid,
'#description' => t('Add your own category.'),
'#weight' => $form['taxonomy'][$vid]['#weight'] + 0.01,
'#prefix' => '',
'#suffix' => '
',
);
// Get any previously queued new term.
if (!empty($form['nid']['#value'])) {
if ($name = taxonomy_other_queue($form['nid']['#value'], $vid)) {
$form['taxonomy']['taxonomy_other_'. $vid]['#default_value'] = $name;
$form['taxonomy'][$vid]['#value'] = 'taxonomy_other';
}
}
// Save '#required' setting for later.
if (isset($form['taxonomy'][$vid]['#required']) && $form['taxonomy'][$vid]['#required']) {
taxonomy_other_required($vid, TRUE);
}
// Count.
$new_fields++;
}
}
}
// If we've added fields, add javascript.
if ($new_fields) {
$form['#validate']['taxonomy_other_node_form_validate'] = array();
drupal_add_js(drupal_get_path('module', 'taxonomy_other') . '/taxonomy_other.js');
}
}
// Register submit callback for 'node_admin_nodes'.
if ($form_id == 'node_admin_nodes') {
$form['#submit']['taxonomy_other_node_admin_nodes_submit'] = array();
}
}
/**
* Validate callback for 'taxonomy_form_vocabulary'.
*/
function taxonomy_other_taxonomy_form_vocabulary_validate($form_id, &$form) {
// Don't allow both 'Multiple select' and taxonomy_other.
if (!empty($form['multiple']) && !empty($form['taxonomy_other'])) {
form_set_error('taxonomy_other', t('Sorry, %mtitle and %ttitle cannot both be checked.',
array('%mtitle' => t('Multiple select'), '%ttitle' => t('Users can add terms'))));
}
}
/**
* Submit callback for 'taxonomy_form_vocabulary'.
* Saves settings to variables 'taxonomy_other_vids' and 'taxonomy_other_show_terms_vids'.
*/
function taxonomy_other_taxonomy_form_vocabulary_submit($form_id, &$form) {
$vid = $form['vid'];
foreach (array('taxonomy_other', 'taxonomy_other_show_terms') as $setting) {
$vids = variable_get($setting . '_vids', array());
if (!empty($form[$setting])) {
$vids[$vid] = $vid;
}
else {
unset($vids[$vid]);
}
variable_set($setting . '_vids', $vids);
}
}
/**
* Submit callback for 'node_admin_nodes'.
*/
function taxonomy_other_node_admin_nodes_submit($form_id, &$form) {
// Force our nodeapi 'update' when nodes are published.
if ($form['operation'] == 'publish') {
foreach (array_filter($form['nodes']) as $nid) {
$node = node_load($nid);
taxonomy_other_nodeapi($node, 'update');
}
}
}
/**
* Validation callback for '*_node_form'.
*/
function taxonomy_other_node_form_validate($form_id, $form) {
foreach(variable_get('taxonomy_other_vids', array()) as $vid) {
if (!empty($form['taxonomy']['taxonomy_other_' . $vid])) {
// Queue the new term for creation on node insert/update.
$name = $form['taxonomy']['taxonomy_other_' . $vid];
taxonomy_other_queue('', $vid, $name);
}
elseif ($form['taxonomy'][$vid] == 'taxonomy_other' && taxonomy_other_required($vid)) {
$vocabulary = taxonomy_get_vocabulary($vid);
form_set_error('taxonomy][' . $vid, t('!name field is required.', array('!name' => $vocabulary->name)));
}
}
}
/**
* Track taxonomy vocabulary '#required' settings.
*/
function taxonomy_other_required($vid, $value = FALSE) {
static $required = array();
if ($value) {
$required[$vid] = $value;
}
return (isset($required[$vid]) && $required[$vid]);
}
/**
* Keep track of new terms for unpublished nodes.
*
* - If $nid, $vid and $name are specified, save the term in the database queue.
* - If $vid and $name are specified, save the term in the static queue.
* - If $nid and $vid are specified, retrieve the term from the queue.
* - If only $nid is specified, retrieve all the terms from the static and database queue.
* - If $nid is empty, retrieve the terms from the static queue.
*
* @param $nid
* Node id.
* @param $vid
* Vocabulary id.
* @param $name
* Name of the new term.
*
* @return
* Depends on the arguments.
*/
function taxonomy_other_queue($nid = '', $vid = '', $name = '') {
static $q = array();
if ($nid && $vid && $name) {
db_query("DELETE FROM {taxonomy_other_queue} WHERE nid = %d AND vid = %d", $nid, $vid);
return db_query("INSERT INTO {taxonomy_other_queue} (nid, vid, name) values(%d, %d, '%s')", $nid, $vid, $name);
}
elseif ($vid && $name) {
$q[$vid] = $name;
}
elseif ($nid && $vid) {
return db_result(db_query("SELECT name FROM {taxonomy_other_queue} WHERE nid = %d AND vid = %d", $nid, $vid));
}
elseif ($nid) {
$result = db_query("SELECT vid, name FROM {taxonomy_other_queue} WHERE nid = %d", $nid);
while ($term = db_fetch_object($result)) {
if (!isset($q[$term->vid])) {
$q[$term->vid] = $term->name;
}
}
}
return $q;
}
/**
* Remove queued terms for a node.
*/
function taxonomy_other_dequeue($nid) {
return db_query("DELETE FROM {taxonomy_other_queue} WHERE nid = %d", $nid);
}
/**
* Create the term and assign it to the node.
*/
function taxonomy_other_save(&$node, $vid, $name) {
// Check for duplicates because taxonomy_save_term() doesn't.
foreach (taxonomy_get_term_by_name($name) as $t) {
if ($vid == $t->vid) {
$term = (array) $t;
break;
}
}
// Not a duplicate?
if (empty($term)) {
// Create term.
$term = array('vid' => $vid, 'name' => $name, 'tid' => 0, 'description' => '', 'weight' => 0);
taxonomy_save_term($term);
// Remember this module created it.
db_query("INSERT INTO {taxonomy_other_term} (tid) VALUES (%d)", $term['tid']);
}
// Assign term to node.
$node->taxonomy[$vid] = $term['tid'];
taxonomy_node_save($node->nid, $node->taxonomy);
return $term;
}
/**
* Get the terms for a vocabulary that were created by this module.
*
* @param $vid
* A vocabulary id.
* @return
* An array of terms.
*/
function taxonomy_other_get_tids($vid) {
$tids = array();
$result = db_query("SELECT t.tid FROM {term_data} t INNER JOIN {taxonomy_other_term} ot ON (t.tid = ot.tid) WHERE t.vid = %d", $vid);
while ($term = db_fetch_object($result)) {
$tids[] = $term->tid;
}
return $tids;
}
/**
* Implementation of hook_nodeapi().
*/
function taxonomy_other_nodeapi(&$node, $op) {
if ($op == 'submit') {
// Clean up $node->taxonomy before the taxonomy module sees it.
foreach (array_keys(taxonomy_other_queue($node->nid)) as $vid) {
unset($node->taxonomy[$vid]);
unset($node->taxonomy['taxonomy_other_' . $vid]);
}
}
elseif ($op == 'insert' || $op == 'update') {
foreach (taxonomy_other_queue($node->nid) as $vid => $name) {
if ($node->status) {
taxonomy_other_save($node, $vid, $name);
taxonomy_other_dequeue($node->nid);
}
else { // Not published, just queue...
taxonomy_other_queue($node->nid, $vid, $name); // Add to db queue.
}
}
}
elseif ($op == 'delete') {
taxonomy_other_dequeue($node->nid); // Delete from db queue.
}
}
/**
* Implementation of hook_taxonomy().
*/
function taxonomy_other_taxonomy($op, $type, $array) {
if ($op == 'delete') {
if ($type == 'vocabulary') {
$terms = taxonomy_other_get_tids($array['vid']);
if (!empty($terms)) {
$d = implode(',', array_pad(array(), count($terms), '%d'));
db_query("DELETE FROM {taxonomy_other_term} WHERE tid IN (" . $d . ")", $terms);
}
}
elseif ($type == 'term') {
db_query("DELETE FROM {taxonomy_other_term} WHERE tid = '%d'", $array['tid']);
}
}
}