t('HSD config'), 'access arguments' => array('administer content types'), 'page callback' => 'drupal_get_form', 'page arguments' => array('hs_content_taxonomy_description_config_form', 3, 5), 'type' => MENU_NORMAL_ITEM, 'file' => 'hs_content_taxonomy_description.admin.inc', ); return $items; } /** * Implementation of hook_form_alter(). */ function hs_content_taxonomy_description_form_alter(&$form, $form_state, $form_id) { if (isset($form['type']) && isset($form['type']['#value']) && $form['type']['#value'] .'_node_form' == $form_id) { if (isset($form['#field_info']) && count($form['#field_info']) > 0) { foreach ($form['#field_info'] as $field_name => &$field_info) { if ($field_info['widget']['type'] == 'content_taxonomy_hsd') { $form['#submit'][] = 'hs_content_taxonomy_form_submit'; break; } } } } } /** * Implementation of hook_form_FORM_ID_alter() */ function hs_content_taxonomy_description_form_content_field_edit_form_alter(&$form, &$form_state) { if ($form['#field']['widget']['type'] == 'content_taxonomy_hsd') { $form['field']['multiple']['#attributes'] = array('disabled' => 'disabled'); $form['field']['multiple']['#description'] = t( 'This setting is now managed by the Hierarchical Select widget configuration!' ); } } //---------------------------------------------------------------------------- // Forms API callbacks. /** * Submit handler for HS CT field form */ function hs_content_taxonomy_description_form_submit(&$form, &$form_state) { foreach ($form['#field_info'] as $field_name => $field_info) { if ($field_info['widget']['type'] == 'content_taxonomy_hsd') { // Change format of values to the one Content Taxonomy expects if (is_array($form_state['values'][$field_name]['tids'])) { $values = array(); foreach($form_state['values'][$field_name]['tids'] as $tid) { $values[] = array('value' => $tid); array_unshift($form_state['values'][$field_name], array('value' => $tid)); } $form_state['values'][$field_name]['tids'] = $values; } else { $values[] = array('value' => $form_state['values'][$field_name]['tids']); array_unshift($form_state['values'][$field_name],array('value' => $form_state['values'][$field_name]['tids'])); $form_state['values'][$field_name]['tids'] = $values; } } } } //---------------------------------------------------------------------------- // CCK hooks. /** * Implementation of hook_widget_info(). */ function hs_content_taxonomy_description_widget_info() { return array( 'content_taxonomy_hsd' => array( // 'content_taxonomy_hsd' instead of 'content_taxonomy_hierarchical_select' due to CCK limitations. 'label' => 'Hierarchical Select Description', 'field types' => array('content_taxonomy'), // Set multiple settings to be handled by widget rather than by CCK itself 'multiple values' => CONTENT_HANDLE_MODULE, 'callbacks' => array( 'default value' => CONTENT_CALLBACK_DEFAULT, ), ), ); } /** * Implementation of hook_widget_settings(). */ function hs_content_taxonomy_description_widget_settings($op, $widget) { switch ($op) { case 'form': drupal_add_css(drupal_get_path('module', 'hs_content_taxonomy_description') .'/hs_content_taxonomy_description.css'); $context = _hs_content_taxonomy_description_parse_context_from_url(); list($content_type_name, $field_name) = $context; $url = 'admin/content/node-type/'. $content_type_name .'/fields/'. $field_name .'/hsd_config'; $items[] = t( "Due to limitations of CCK, there is a separate form to configure this Hierarchical Select widget's settings.",array('!url' => url($url)) ); $placeholders = array( '%multiple_values' => t('Multiple values'), '%enable_the_dropbox' => t('Enable the dropbox'), '%save_term_lineage' => t('Save term lineage'), ); $items[] = t( 'The %multiple_values field setting is now managed by the Hierarchical Select module: it will be enabled when either the %enable_the_dropbox or %save_term_lineage settings (or both) are enabled.', $placeholders ); $form['hsd_config'] = array( '#type' => 'fieldset', '#title' => t('Hierarchical Select configuration'), '#description' => '
'. 'Important!'. '
'. theme('item_list', $items), '#collapsible' => FALSE, ); return $form; case 'callbacks': return array('default value' => CONTENT_CALLBACK_NONE); } } /** * Implementation of hook_widget(). */ function hs_content_taxonomy_description_widget(&$form, &$form_state, $field, $items, $delta = 0) { $field_name = $field['field_name']; $vid = $field['vid']; $tid = content_taxonomy_field_get_parent($field); $depth = (empty($field['depth'])) ? 0 : $field['depth']; require_once(drupal_get_path('module', 'hierarchical_select') .'/includes/common.inc'); $node = &$form['#node']; // Extremely ugly checks because CCK/Content Taxonomy is a big failure. $selected_items = array(); if (isset($items[$field_name])) { // New node: "default value" is the default value from field settings. if (isset($items[$field_name]['tids'])) { // Multiple default values as a field setting. if (is_array($items[$field_name]['tids'])) { foreach ($items[$field_name]['tids'] as $item) { $selected_items[] = $item['value']; } } // Single default value as a field setting. else { $selected_items[] = $items[$field_name]['tids']; } } } else { // Existing node: "default value" are the previously selected terms. foreach ($items as $item) { $selected_items[] = $item['value']; } } $node_field = &$node->$field_name; $form[$field_name]['#tree'] = TRUE; $form[$field_name]['#weight'] = $field['widget']['weight']; $form[$field_name]['tids'] = array( '#title' => t($field['widget']['label']), '#type' => 'hierarchical_select', '#weight' => $field['widget']['weight'], '#config' => array( 'module' => 'hs_content_taxonomy_description', 'params' => array( 'vid' => $vid, 'tid' => $tid, 'depth' => $depth, ), ), '#required' => $field['required'], '#description' => t($field['widget']['description']), '#default_value' => !empty($selected_items) ? array_values($selected_items) : array(), ); unset($form[$field_name]['#options']); // Unset to prevent passing around of possibly huge HTML. unset($form[$field_name]['#theme']); // Unset to prevent theme_taxonomy_term_select() from running. hierarchical_select_common_config_apply($form[$field_name]['tids'], "content-taxonomy-$field_name"); return $form; } //------------------------------------------------------------------------------------------------------- // HS Content Taxonomy CCK formatters /** * Implementation of hook_theme(). */ function hs_content_taxonomy_description_theme() { return array( 'hs_content_taxonomy_description_formatter_hierarchical_text' => array( 'arguments' => array('element' => NULL), 'function' => 'theme_hs_content_taxonomy_description_formatter_hierarchical', ), 'hs_content_taxonomy_description_formatter_hierarchical_links' => array( 'arguments' => array('element' => NULL), 'function' => 'theme_hs_content_taxonomy_description_formatter_hierarchical', ), 'hs_content_taxonomy_description_row' => array( 'arguments' => array('row' => NULL, 'type' => NULL), ), ); } /** * Implementation of hook_field_formatter_info(). */ function hs_content_taxonomy_description_field_formatter_info() { return array( 'hierarchical_text' => array( 'label' => t('As hierarchical text'), 'field types' => array('content_taxonomy'), 'multiple values' => CONTENT_HANDLE_MODULE, ), 'hierarchical_links' => array( 'label' => t('As hierarchical links'), 'field types' => array('content_taxonomy'), 'multiple values' => CONTENT_HANDLE_MODULE, ), ); } /** * Theme function to output single row (lineage) of CT field * * Giving levels different classes so some funny theming is possible: * for example, different font size depending on level (like tagadelic) */ function theme_hs_content_taxonomy_description_row($row, $type) { $separator = '›'; $output = ''; if (empty($row)) { return $output; } $items = array(); foreach ($row as $level => $item ) { $term = taxonomy_get_term($item['value']); _content_taxonomy_localize_term($term); $line = ''; // Depending on which formatter is active, create links or use labels. switch ($type) { case 'hierarchical_links': $line .= l($term->name . HS_CONTENT_TAXONOMY_DESCRIPTION_SEP . $term->description, taxonomy_term_path($term), array('rel' => 'tag', 'title' => $term->description)); break; case 'hierarchical_text': $line .= $item['label'] . HS_CONTENT_TAXONOMY_DESCRIPTION_SEP . $term->description; break; } $line .= ''; $items[] = $line; } $output = implode($separator , $items); return $output; } /** * Theme function for HS Content Taxonomy formatters. * */ function theme_hs_content_taxonomy_description_formatter_hierarchical($element) { $output = ''; // Extract required field information. // $element contains only field name; so we use cck function to get more info. $field = content_fields($element['#field_name'], $element['#type_name']); $field_name = $field['field_name']; $vid = $field['vid']; $tid = (empty($field['tid'])) ? 0 : $field['tid']; $depth = (empty($field['depth'])) ? 0 : $field['depth']; // Get the config for this field. require_once(drupal_get_path('module', 'hierarchical_select') .'/includes/common.inc'); $config_id = "content-taxonomy-$field_name"; $config = hierarchical_select_common_config_get($config_id); $config += array( 'module' => 'hs_content_taxonomy_description', 'params' => array( 'vid' => $vid, 'tid' => $tid, 'depth' => $depth, ), ); $selection = array(); // Cycle through elements. foreach (element_children($element) as $key) { if (isset($element[$key]['#item']['value'])) { $selection[] = $element[$key]['#item']['value']; } } // It is said that formatter theme function is called even if field is empty. if (empty($selection)) { return $output; } // Generate a dropbox out of the selection. This will automatically // calculate all lineages for us. $dropbox = _hierarchical_select_dropbox_generate($config, $selection); // Actual formatting. // In 6.x formatter is fully themable // We theme each lineage using additional theme function $num_items = count($dropbox->lineages); $flip = array('even' => 'odd', 'odd' => 'even'); $class = 'even'; $output = '