'.t('The taxonomy_fields module brings two important modules together: CCK and taxonomy. As CCK can assign fields to content types, taxonomy_fields can assign CCK fields to categories. By doing this, content types are not limited to the same range of fields anymore.
Nodes of the same content type can now contain absolutely different fields. Simply assign a field to a term and every node in this category will now contain this field. When choosing a new term for a node, the field-form will appear next time on the edit-page.').'
';
$output.=t('Further more taxonomy_fields gives you two extra options:
- Universal values for fields. When activated, this field will always carry the same value for this term, users can not edit the value. This option can be used for standard disclaimers for example. Does not work with image-fields and file-fields.
- Ancestor fields. When activated, all nodes will show the fields of all ancestors of this term. Can be used with single and multiple hierarchies, so you don\'t have to assign the same field to all of your sub-categories.
');
$output .= t('You can
', array('@add_existing' => url('admin/content/taxonomy_fields/add_existing'),'@add_new' => url('admin/content/taxonomy_fields/add_new'),
'@taxonomy_fields' => url('admin/content/taxonomy_fields'), '@content_types' => url('admin/content/types')));
return $output;
case 'admin/content/taxonomy_fields':
return t('Taxonomy fields are CCK fields assigned to terms. They show up for every node in a category.
Make sure you enable the \'taxonomy fields\' setting in the content types settings!
', array('!content_type_settings' => url('admin/content/types')));
}
}
/**
* Implementation of hook_perm().
*/
function taxonomy_fields_perm() {
return array('administer taxonomy_fields');
}
/**
* Implementation of hook_menu().
*/
function taxonomy_fields_menu($may_cache) {
$items = array();
$access = user_access('administer taxonomy_fields');
if ($may_cache) {
$items[] = array(
'path' => 'admin/content/taxonomy_fields',
'title' => t('Taxonomy fields'),
'callback' => '_taxonomy_fields_list',
'access' => $access,
'description' => t("Assign CCK fields to categories."),
);
$items[] = array(
'path' => 'admin/content/taxonomy_fields/manage_taxonomy_fields',
'title' => t('manage taxonomy fields'),
'type' => MENU_DEFAULT_LOCAL_TASK,
'weight' => -10,
);
$items[] = array(
'path' => 'admin/content/taxonomy_fields/manage_terms',
'title' => t('manage terms'),
'type' => MENU_LOCAL_TASK,
'callback' => 'drupal_get_form',
'callback arguments' => array('_taxonomy_fields_manage_terms_form'),
'access' => $access,
);
$items[] = array(
'path' => 'admin/content/taxonomy_fields/add_existing',
'title' => t('add existing field'),
'type' => MENU_LOCAL_TASK,
'callback' => '_taxonomy_fields_term_field_relation_add_existing',
'access' => $access,
);
$items[] = array(
'path' => 'admin/content/taxonomy_fields/add_new',
'title' => t('add new field'),
'type' => MENU_LOCAL_TASK,
'callback' => '_taxonomy_fields_term_field_relation_add_new',
'access' => $access,
);
}
else {
if (arg(0) == 'admin' && arg(1) == 'content' && arg(2) == 'taxonomy_fields' && is_numeric(arg(3))) {
$term = taxonomy_fields_terms(arg(3));
$tid = arg(3);
$items[] = array(
'path' => 'admin/content/taxonomy_fields/'. arg(3),
'title' => t($term['name']),
'callback' => 'drupal_get_form',
'callback arguments' => array('_taxonomy_fields_term'),
'access' => $access,
'type' => MENU_CALLBACK,
);
$items[] = array(
'path' => 'admin/content/taxonomy_fields/'. arg(3).'/edit',
'title' => t('term settings'),
'type' => MENU_DEFAULT_LOCAL_TASK,
'weight' => -10,
);
$items[] = array(
'path' => 'admin/content/taxonomy_fields/'. arg(3).'/fields',
'title' => t('display settings'),
'type' => MENU_LOCAL_TASK,
'callback' => 'drupal_get_form',
'callback arguments' => array('taxonomy_fields_display_overview_form'),
'access' => $access,
);
if (arg(4) == 'fields' && arg(5) && isset($term['fields'][arg(5)])) {
$items[] = array(
'path' => 'admin/content/taxonomy_fields/'. arg(3) .'/fields/'. arg(5),
'title' => t($term['fields'][arg(5)]['widget']['label']),
'callback' => 'drupal_get_form',
'access' => $access,
'callback arguments' => array('_taxonomy_fields_edit_field',arg(3), arg(5)),
'type' => MENU_CALLBACK,
);
$items[] = array(
'path' => 'admin/content/taxonomy_fields/'. arg(3) .'/fields/'. arg(5) .'/remove',
'title' => t('remove field'),
'callback' => 'drupal_get_form',
'access' => $access,
'callback arguments' => array('_taxonomy_fields_edit_field_remove',arg(3), arg(5)),
'type' => MENU_CALLBACK,
);
}
}
}
return $items;
}
/**
* Menu callback; lists all terms and fields used by taxonomy_fields.
*/
function _taxonomy_fields_list(){
//needs call because content.module could have changed database storage
taxonomy_fields_clear_terms_cache();
//output of all existing term-field-relations
//$query=db_query("SELECT SUBSTRING(nfi.type_name,14) AS tid, tfa.ancestors, tf.universal, td.name, nfi.field_name, nfi.type_name, nfi.label, nfi.widget_type, nfi.weight, nf.type
$query=db_query("SELECT SUBSTRING(nfi.type_name,14) AS tid, tf.universal, tfa.ancestors, td.vid, td.name, td.weight AS t_weight, th.parent, nfi.field_name, nfi.type_name, nfi.label, nfi.widget_type, nfi.weight, nf.type
FROM {node_field_instance} nfi
LEFT JOIN {taxonomy_fields} tf ON nfi.field_name=tf.field_name AND SUBSTRING(nfi.type_name,14)=tf.tid
LEFT JOIN {taxonomy_fields_ancestors} tfa ON SUBSTRING(nfi.type_name,14)=tfa.tid
LEFT JOIN {term_data} td ON SUBSTRING(nfi.type_name,14)=td.tid
LEFT JOIN {term_hierarchy} th ON SUBSTRING(nfi.type_name,14)=th.tid
LEFT JOIN {node_field} nf ON nf.field_name=nfi.field_name
LEFT JOIN {variable} v ON td.vid=SUBSTRING(v.name,16)
WHERE nfi.type_name LIKE 'term_related_%%' AND v.name LIKE 'tax_fields_voc_%%' AND v.value='s:1:\"1\";' AND ((tf.delta IS NULL OR tf.delta=0 ) OR (tf.delta=1 AND tf.delta!=0))
ORDER BY td.vid, t_weight, td.name, nfi.weight");
//ORDER BY td.name, nfi.weight");
$output.='Fields assigned to terms:
';
$field_output=array();
while($field_list=db_fetch_object($query)){
//check if term is still existing and delete fields if not
if(!$field_list->name){
db_query('DELETE FROM {taxonomy_fields_ancestors} WHERE tid=%d',$field_list->tid);
taxonomy_fields_field_instance_delete(array('tid'=>$field_list->tid,'field_name'=>$field_list->field_name));
}
else{
if($field_list->ancestors){
$field_output[$field_list->tid]['ancestors']=TRUE;
}
$field_output[$field_list->tid]['rows'][$field_list->field_name]=array($field_list->label,$field_list->field_name,$field_list->type,$field_list->widget_type,$field_list->weight);
if($field_list->universal){
$field_output[$field_list->tid]['rows'][$field_list->field_name][]=t('universal field');
}
else {
$field_output[$field_list->tid]['rows'][$field_list->field_name][]=t('');
}
$field_output[$field_list->tid]['rows'][$field_list->field_name][]=l(t('edit'), 'admin/content/taxonomy_fields/'.ltrim(strrchr($field_list->type_name,'_'),'_').'/fields/'.$field_list->field_name);
$field_output[$field_list->tid]['rows'][$field_list->field_name][]=l(t('remove'), 'admin/content/taxonomy_fields/'.ltrim(strrchr($field_list->type_name,'_'),'_').'/fields/'.$field_list->field_name.'/remove');
$field_output[$field_list->tid]['name']=$field_list->name;
$field_output[$field_list->tid]['vid'] = $field_list->vid;
$field_output[$field_list->tid]['weight'] = $field_list->t_weight;
$field_output[$field_list->tid]['parent'] = $field_list->parent;
}
}
if($field_output){
$output.=theme('taxonomy_fields_list_output',$field_output);
}
else{
$output.='No fields are assigned to terms.';
}
return $output;
}
/**
* Menu callback; presents the form to go to term settings.
*/
function _taxonomy_fields_manage_terms_form(){
$vocabulary=module_invoke('taxonomy','get_vocabularies');
$form = array();
$voc_form=array();
foreach ($vocabulary as $voc){
$vid=$voc->vid;
$voc_form[$vid]=module_invoke('taxonomy','form',$vid);
}
foreach ($voc_form as $key => $value){
$voc_form[$key]['#multiple']=0;
$voc_form[$key]['#size']=0;
}
$form['voc'] = array(
'#type' => 'fieldset',
'#title' => t('Select a term to edit the term settings'),
);
foreach ($voc_form as $key => $value){
$form['voc'][$key]=$value;
}
$form['voc']['button']=array(
'#type' => 'submit',
'#value' => t('Term settings'),
);
return $form;
}
function _taxonomy_fields_manage_terms_form_submit($form_id, $form_values){
foreach ($form_values as $key => $value){
if (is_numeric($key)){
if($value){
return 'admin/content/taxonomy_fields/'.$value.'/edit';
}
}
}
}
/**
* Menu callback; presents the form to alter ancestor fields setting.
*/
function _taxonomy_fields_term(){
$tid = arg(3);
$query=db_query('SELECT ancestors FROM {taxonomy_fields_ancestors} WHERE tid=%d',$tid);
$result=db_fetch_array($query);
$ancestors = taxonomy_fields_get_ancestor_fields($tid);
//ancestors of $tid and their fields
$ancestor_output='';
if(empty($ancestors)){
$ancestor_output.='none';
}
else{
foreach($ancestors as $ancestor){
$ancestor_output.=$ancestor['widget']['label'].' ('.$ancestor['field_name'].') assigned to '.$ancestor['term'].'
';
}
}
$form = array();
$form['ancestors'] = array(
'#type' => 'fieldset',
'#title' => t('Term ancestor fields setting'),
'#description' => t('
This setting applies to every node with taxonomy_fields carrying this term.
Fields of ancestor-terms to this term are:
!ancestor_output', array('!ancestor_output' => $ancestor_output)),
);
$form['ancestors']['ancestors'] = array(
'#type' => 'checkbox',
'#title' => t('Display ancestor-fields'),
'#default_value' => $result ? $result['ancestors'] : 0,
'#description' => t('All fields of ancestor-terms will be displayed for this term.'),
);
$form['tid'] = array(
'#type' => 'value',
'#value' => arg(3),
);
$form['submit'] = array(
'#type' => 'submit',
'#value' => t('Save term settings'),
);
return $form;
}
function _taxonomy_fields_term_submit($form_id, $form_values){
db_query("DELETE FROM {taxonomy_fields_ancestors} WHERE tid = %d", $form_values['tid']);
db_query("INSERT INTO {taxonomy_fields_ancestors} SET ancestors = %d, tid = %d", $form_values['ancestors'], $form_values['tid']);
drupal_set_message(t('The term was updated.'));
}
/**
* Menu callback; presents the form for creating a new field.
*/
function _taxonomy_fields_term_field_relation_add_new(){
$form = array();
$type = taxonomy_fields_terms();
$field_types = _taxonomy_fields_field_types();
$fields = taxonomy_fields_fields();
$widget_types = _taxonomy_fields_widget_types();
$vocabulary=module_invoke('taxonomy','get_vocabularies');
foreach ($vocabulary as $vid => $voc){
if(!variable_get('tax_fields_voc_'.$vid,0)){
unset($vocabulary[$vid]);
}
}
if(empty($vocabulary)){
form_set_error('no vocabulary',t('No vocabulary existing. You need to create vocabulary to assign fields.'));
}
// forms for new fields
$field_type_options = array();
foreach ($field_types as $field_name => $field_type) {
foreach ($widget_types as $widget_name => $widget_type) {
if (in_array($field_name, $widget_type['field types'])) {
$field_type_options[$field_name .'-'. $widget_name] = $widget_type['label'];
}
}
}
if (count($field_type_options) > 0) {
$output .= drupal_get_form('_taxonomy_fields_term_field_relation_add_new_form', $vocabulary, $field_type_options);
}
else {
form_set_error('no field module',t('No field modules are enabled. You need to enable one, such as text.module, before you can add new fields.', array('!modules_url' => url('admin/build/modules'))));
}
return $output;
}
function _taxonomy_fields_term_field_relation_add_new_form($vocabulary,$field_type_options){
$form = array();
$form['voc'] = array(
'#type' => 'fieldset',
'#title' => t('Select vocabulary to create and assign a new field'),
);
foreach ($vocabulary as $voc){
$vid=$voc->vid;
$form['voc']['term'][$vid]=module_invoke('taxonomy','form',$vid);
if($form['voc']['term'][$vid]['#options'][0] != ''){
array_unshift($form['voc']['term'][$vid]['#options'],'');
$form['voc']['term'][$vid]['#default_value']=0;
if($form['voc']['term'][$vid]['#multiple']){
$form['voc']['term'][$vid]['#size']++;
}
}
}
$form['voc']['new'] = array(
'#type' => 'fieldset',
'#title' => t('Create new field'),
);
$form['voc']['new']['widget']['label'] = array(
'#title' => t('Label'),
'#type' => 'textfield',
'#default_value' => '',
'#description' => t('The human-readable name of this field.'),
'#required' => TRUE,
);
$form['voc']['new']['field_widget_type'] = array(
'#type' => 'radios',
'#title' => t('Field type'),
'#required' => TRUE,
'#options' => $field_type_options,
'#theme' => 'taxonomy_fields_field_add_new_field_widget_type',
);
$form['voc']['new']['submit'] = array(
'#type' => 'submit',
'#value' => t('Create field'),
);
return $form;
}
function _taxonomy_fields_term_field_relation_add_new_form_validate($form_id, $form_values) {
$term_selected=FALSE;
foreach ($form_values as $key => $value){
if (is_numeric($key)){
if (is_array($form_values[$key])){
foreach ($form_values[$key] as $key2 => $value2){
if($value2){
$term_selected=TRUE;
}
}
}
else{
if($value){
$term_selected=TRUE;
}
}
}
}
if(!$term_selected){
form_set_error('no term select',t('No terms were selected. You need to select at least one term to add new fields.'));
}
}
function _taxonomy_fields_term_field_relation_add_new_form_submit($form_id, $form_values) {
// Find a valid, computer-friendly field name.
$fields = taxonomy_fields_fields();
$field_name = trim($form_values['label']);
$field_name = drupal_strtolower($field_name);
$field_name = str_replace(array(' ', '-'), '_', $field_name);
$field_name = preg_replace('/[^a-z0-9_]/', '', $field_name);
$field_name = 'field_'. $field_name;
$field_name = substr($field_name, 0, 31);
if (isset($fields[$field_name])) {
$counter = 0;
do {
$new_name = substr($field_name, 0, 29) .'_'. $counter++;
} while (isset($fields[$new_name]));
$field_name = $new_name;
}
$widget_type = explode('-',$form_values['field_widget_type']);
$terms=array();
foreach ($form_values as $key => $value){
if (is_numeric($key)){
if (is_array($form_values[$key])){
foreach ($form_values[$key] as $key2 => $value2){
if($value2){
$terms[]=$value2;
_taxonomy_fields_create_term_table($value2);
db_query("INSERT INTO {node_field_instance} (field_name, type_name, weight, label, widget_type, widget_settings, description) VALUES ('%s', '%s', %d, '%s', '%s', '%s', '%s')", $field_name, 'term_related_'.$value2, 0, $form_values['label'], $widget_type[1], serialize(array()), '');
}
}
}
else{
if($value){
$terms[]=$value;
_taxonomy_fields_create_term_table($value);
db_query("INSERT INTO {node_field_instance} (field_name, type_name, weight, label, widget_type, widget_settings, description) VALUES ('%s', '%s', %d, '%s', '%s', '%s', '%s')", $field_name, 'term_related_'.$value, 0, $form_values['label'], $widget_type[1], serialize(array()), '');
}
}
}
}
if(empty($terms)){
return 'admin/content/taxonomy_fields/add_new';
}
if(count($terms)>1){
$db_storage=CONTENT_DB_STORAGE_PER_FIELD;
}
else{
$db_storage=CONTENT_DB_STORAGE_PER_CONTENT_TYPE;
}
$field_widget_type = explode('-', $form_values['field_widget_type']);
db_query("INSERT INTO {node_field} (field_name, type, global_settings, required, multiple, db_storage) VALUES ('%s', '%s', '%s', %d, %d, %d)", $field_name, $field_widget_type[0], serialize(array()), 0, 0, $db_storage);
taxonomy_fields_clear_terms_cache();
// Create new database columns as necessary.
$field_types = _taxonomy_fields_field_types();
$field_type = $field_types[$field_widget_type[0]];
$field = taxonomy_fields_fields($field_name);
$columns = module_invoke($field_type['module'], 'field_settings', 'database columns', $field);
if (is_array($columns) && count($columns)) {
content_alter_db_field(array(), array(), $field, $columns);
}
drupal_set_message(t('Created field %label.', array('%label' => $form_values['label'])));
return 'admin/content/taxonomy_fields/'.$terms[0].'/fields/'.$field_name;
}
/**
* Menu callback; presents the form for assigning an existing field.
*/
function _taxonomy_fields_term_field_relation_add_existing(){
$fields = taxonomy_fields_fields();
$vocabulary=module_invoke('taxonomy','get_vocabularies');
foreach ($vocabulary as $vid => $voc){
if(!variable_get('tax_fields_voc_'.$vid,0)){
unset($vocabulary[$vid]);
}
}
if(empty($vocabulary)){
form_set_error('no vocabulary',t('No vocabulary existing. You need to create vocabulary to assign fields.'));
}
// list all existing fields
$options = array();
foreach ($fields as $field) {
$options[$field['field_name']] = t($field['widget']['label']) .' ('. $field['field_name'] .')';
}
//select forms for existing fields
if ($options) {
$output.=drupal_get_form('_taxonomy_fields_term_field_relation_add_existing_form',$vocabulary,$options);
}
else{
form_set_error('no fields',t('No fields existing. You need to create fields to assign them to categories.'));
}
return $output;
}
function _taxonomy_fields_term_field_relation_add_existing_form($vocabulary,$options){
$form = array();
$form['voc'] = array(
'#type' => 'fieldset',
'#title' => t('Select vocabulary to assign an existing field'),
);
foreach ($vocabulary as $voc){
$vid=$voc->vid;
$form['voc']['term'][$vid]=module_invoke('taxonomy','form',$vid);
if($form['voc']['term'][$vid]['#options'][0] != ''){
array_unshift($form['voc']['term'][$vid]['#options'],'');
$form['voc']['term'][$vid]['#default_value']=0;
if($form['voc']['term'][$vid]['#multiple']){
$form['voc']['term'][$vid]['#size']++;
}
}
}
$form['voc']['existing'] = array(
'#type' => 'fieldset',
'#title' => t('Assign to existing field'),
);
$form['voc']['existing']['field_name'] = array(
'#type' => 'select',
'#required' => TRUE,
'#options' => $options,
);
$form['voc']['existing']['submit'] = array(
'#type' => 'submit',
'#value' => t('Add field'),
);
return $form;
}
function _taxonomy_fields_term_field_relation_add_existing_form_validate($form_id, $form_values){
$term_selected=FALSE;
$relation_double_up=FALSE;
$terms=taxonomy_fields_terms();
foreach ($form_values as $key => $value){
if (is_numeric($key)){
if (is_array($form_values[$key])){
//term from multiple select vocabulary
foreach ($form_values[$key] as $value2){
if($value2){
$term_selected=TRUE;
}
if(!empty($terms['term_related_'.$value2]['fields'][$form_values['field_name']])){
$relation_double_up=TRUE;
}
}
}
elseif ($value){
//term from single select vocabulary
$term_selected=TRUE;
if(!empty($terms['term_related_'.$value]['fields'][$form_values['field_name']])){
$relation_double_up=TRUE;
}
}
}
}
if(!$term_selected){
form_set_error('no term select',t('No terms were selected. You need to select at least one term to add new fields.'));
}
if($relation_double_up){
drupal_set_message(t('This field is already assigned to some of the selected terms!'));
}
}
function _taxonomy_fields_term_field_relation_add_existing_form_submit($form_id, $form_values){
$change=FALSE;
$terms=taxonomy_fields_terms();
$prior_instance = db_fetch_array(db_query("SELECT weight, label, widget_type, widget_settings, description FROM {node_field_instance} WHERE field_name = '%s'", $form_values['field_name']));
if (!$prior_instance) {
$prior_instance = array();
$prior_instance['weight'] = 0;
$prior_instance['label'] = $form_values['field_name'];
$prior_instance['widget_type'] = '';
$prior_instance['widget_settings'] = '';
$prior_instance['description'] = '';
}
foreach ($form_values as $key => $value){
if (is_numeric($key)){
if (is_array($form_values[$key])){
//term from multiple select vocabulary
foreach ($form_values[$key] as $value2){
if($value2 && empty($terms['term_related_'.$value2]['fields'][$form_values['field_name']])){
$change=TRUE;
_taxonomy_fields_create_term_table($value2);
db_query("INSERT INTO {node_field_instance} (field_name, type_name, weight, label, widget_type, widget_settings, description) VALUES ('%s', '%s', %d, '%s', '%s', '%s', '%s')", $form_values['field_name'], 'term_related_'.$value2, $prior_instance['weight'], $prior_instance['label'], $prior_instance['widget_type'], $prior_instance['widget_settings'], $prior_instance['description']);
}
}
}
elseif ($value && empty($terms['term_related_'.$value]['fields'][$form_values['field_name']])){
//term from single select vocabulary
$change=TRUE;
_taxonomy_fields_create_term_table($value);
db_query("INSERT INTO {node_field_instance} (field_name, type_name, weight, label, widget_type, widget_settings, description) VALUES ('%s', '%s', %d, '%s', '%s', '%s', '%s')", $form_values['field_name'], 'term_related_'.$value, $prior_instance['weight'], $prior_instance['label'], $prior_instance['widget_type'], $prior_instance['widget_settings'], $prior_instance['description']);
}
}
}
if($change){
$field = taxonomy_fields_fields($form_values['field_name']);
$field_types = _taxonomy_fields_field_types();
$field_type = $field_types[$field['type']];
$columns = module_invoke($field_type['module'], 'field_settings', 'database columns', $field);
if (is_array($columns) && count($columns)) {
if ($field['db_storage'] == CONTENT_DB_STORAGE_PER_CONTENT_TYPE) {
$new_field = $field;
$new_field['db_storage'] = CONTENT_DB_STORAGE_PER_FIELD;
db_query("UPDATE {node_field} SET db_storage = %d WHERE field_name = '%s'", CONTENT_DB_STORAGE_PER_FIELD, $form_values['field_name']);
content_alter_db_field($field, $columns, $new_field, $columns);
}
}
taxonomy_fields_clear_terms_cache();
return 'admin/content/taxonomy_fields';
}
else{
return 'admin/content/taxonomy_fields/add_existing';
}
}
/**
* Creates a table 'content_type_related_[$tid]' if not existing
*/
function _taxonomy_fields_create_term_table($tid){
if(!db_table_exists('content_type_term_related_'.$tid)){
switch ($GLOBALS['db_type']) {
case 'mysql':
case 'mysqli':
db_query("CREATE TABLE {content_type_term_related_$tid } (
vid int unsigned NOT NULL default '0',
nid int unsigned NOT NULL default '0',
PRIMARY KEY (vid)
) /*!40100 DEFAULT CHARACTER SET utf8 */;");
break;
case 'pgsql':
db_query("CREATE TABLE {content_type_term_related_$tid } (
vid integer NOT NULL default '0' CHECK(vid >= 0),
nid integer NOT NULL default '0' CHECK(nid >= 0),
PRIMARY KEY (vid)
)");
break;
}
}
}
/**
* Implementation of hook_form_alter().
*/
function taxonomy_fields_form_alter($form_id, &$form) {
switch ($form_id) {
case 'node_type_form':
//check if taxonomy_fields are enabled for this content_type
$enabled = variable_get('taxonomy_fields_'.$form['#node_type']->type, 0);
$form['workflow']['taxonomy_fields'] = array(
'#type' => 'radios',
'#title' => t('Taxonomy fields'),
'#default_value' => $enabled,
'#options' => array(0 => t('Disabled'), 1 => t('Enabled')),
'#description' => t('Should this content type contain fields attached by terms?'),
);
break;
case $form['type']['#value'].'_node_form':
if(variable_get('taxonomy_fields_'.$form['type']['#value'],0)){
$node = $form['#node'];
$in_node = module_invoke('content','types',$node->type);
$return = array();
$widget_types = _taxonomy_fields_widget_types();
$fields=taxonomy_fields_get_node_info($node);
foreach ($fields as $tid => $field_term){
if($field_term['ancestors']){
$field_term['fields'] = array_merge($field_term['fields'],taxonomy_fields_get_ancestor_fields($tid));
}
if($field_term['fields']){
foreach ($field_term['fields'] as $field) {
//don't add already existing fields
//if field_value is set universal then there's no edit widget
if(!isset($in_node['fields'][$field['field_name']]) && !$field['universal']){
$form['#attributes'] = array("enctype" => "multipart/form-data");
$node_field = isset($node->$field['field_name']) ? $node->$field['field_name'] : array();
$module = $widget_types[$field['widget']['type']]['module'];
$function = $module .'_widget';
if (function_exists($function)) {
// If the field is used for he first time with this node, pre-fill with default values
$db_info = module_invoke('content','database_info',$field);
$table = $db_info['table'];
$default_value_query = db_query('SELECT * FROM {'.$table.'} WHERE nid=%d', $node->nid);
$default_value_result = db_fetch_array($default_value_query);
if (empty($default_value_result)) {
$node_field = module_invoke('content','default_value',$node, $field, $node_field);
}
$function('prepare form values', $node, $field, $node_field);
if (isset($node->$field['field_name']) || count($node_field)) {
$node->$field['field_name'] = $node_field;
}
$result = $function('form', $node, $field, $node_field);
if (is_array($result)) {
$result[$field['field_name']]['#weight'] = $field['widget']['weight'];
$return = array_merge($return, $result);
}
else if (isset($result)) {
$return[] = $result;
}
$in_node['fields'][$field['field_name']]=$field;
}
if (is_object($node) && (isset($node->$field['field_name']) || count($node_field))) {
$node->$field['field_name'] = $node_field;
}
}
}
}
}
$form = array_merge($form, $return);
}
break;
case 'taxonomy_form_vocabulary':
$enabled = variable_get('tax_fields_voc_'.$form['vid']['#value'],0);
$form['submit']['#weight'] = 8;
if($form['delete']) {
$form['delete']['#weight'] = 8;
}
$form['taxonomy_fields'] = array(
'#type' => 'fieldset',
'#title' => t('Taxonomy fields'),
'#weight' => 5,
);
$form['taxonomy_fields']['tax_fields'] = array(
'#type' => 'radios',
//'#title' => t('Taxonomy fields setting'),
'#default_value' => $enabled,
'#options' => array(0 => t('Disabled'), 1 => t('Enabled')),
'#description' => t('Should this vocabulary carry fields?'),
);
break;
}
}
/**
* Implementation of hook_nodeapi().
*/
function taxonomy_fields_nodeapi(&$node, $op, $teaser, $page) {
if(variable_get('taxonomy_fields_'.$node->type,0)){
$fields=taxonomy_fields_get_node_info($node);
switch ($op) {
case 'load':
$in_node=module_invoke('content','types',$node->type);
$return=array();
foreach ($fields as $tid => $field_term) {
if($field_term['ancestors']){
$field_term['fields']=array_merge($field_term['fields'],taxonomy_fields_get_ancestor_fields($tid));
}
if($field_term['fields']){
foreach($field_term['fields'] as $field){
if(!isset($in_node['fields'][$field['field_name']])){
$universal=FALSE;
$query=db_query('SELECT tf.field_value, tf.universal,tf.delta FROM {taxonomy_fields} tf WHERE tf.field_name="%s" AND tf.tid=%d',$field['field_name'], ltrim(strrchr($field['type_name'],'_'),'_'));
$node_field = isset($node->$field['field_name']) ? $node->$field['field_name'] : array();
while($result2=db_fetch_object($query)){
if($result2->universal){
$universal=TRUE;
$node_field[$result2->delta]=unserialize($result2->field_value);
}
}
if(!$universal){
$default_additions = _taxonomy_fields_field_invoke_default($op, $node, $field, $teaser, $page);
if ($default_additions) {
foreach ($default_additions as $key => $value) {
$node->$key = $value;
}
}
$additions = _taxonomy_fields_field_invoke('load', $node, $field);
if ($additions) {
foreach ($additions as $key => $value) {
$default_additions[$key] = $value;
}
}
}
else{
$default_additions[$field['field_name']]=$node_field;
$node->$field['field_name']=$node_field;
}
}
}
}
}
return $default_additions;
break;
case 'insert':
foreach ($fields as $tid => $field_term){
if($field_term['ancestors']){
$field_term['fields']=array_merge($field_term['fields'],taxonomy_fields_get_ancestor_fields($tid));
}
if($field_term['fields']){
foreach($field_term['fields'] as $field){
if(!$field['universal']){
_taxonomy_fields_field_invoke('insert', $node, $field);
_taxonomy_fields_field_invoke_default('insert', $node, $field);
}
}
}
}
break;
case 'update':
foreach ($fields as $tid => $field_term){
if($field_term['ancestors']){
$field_term['fields']=array_merge($field_term['fields'],taxonomy_fields_get_ancestor_fields($tid));
}
if($field_term['fields']){
foreach($field_term['fields'] as $field){
if(!$field['universal']){
_taxonomy_fields_field_invoke('update', $node, $field);
_taxonomy_fields_field_invoke_default('update', $node, $field);
}
}
}
}
break;
case 'delete':
foreach ($fields as $tid => $field_term){
if($field_term['ancestors']){
$field_term['fields']=array_merge($field_term['fields'],taxonomy_fields_get_ancestor_fields($tid));
}
if($field_term['fields']){
foreach($field_term['fields'] as $field){
if(!$field['universal']){
_taxonomy_fields_field_invoke('delete', $node, $field);
_taxonomy_fields_field_invoke_default('delete', $node, $field);
}
}
}
}
break;
case 'delete revision':
foreach ($fields as $tid => $field_term){
if($field_term['ancestors']){
$field_term['fields']=array_merge($field_term['fields'],taxonomy_fields_get_ancestor_fields($tid));
}
if($field_term['fields']){
foreach($field_term['fields'] as $field){
if(!$field['universal']){
_taxonomy_fields_field_invoke('delete revision', $node, $field);
_taxonomy_fields_field_invoke_default('delete revision', $node, $field);
}
}
}
}
break;
case 'view':
//list information of this content_type to check if a field already exists
$in_node=module_invoke('content','types',$node->type);
$return=array();
foreach ($fields as $tid => $field_term) {
if($field_term['ancestors']){
$field_term['fields']=array_merge($field_term['fields'],taxonomy_fields_get_ancestor_fields($tid));
}
if($field_term['fields']){
foreach($field_term['fields'] as $field){
if(!isset($in_node['fields'][$field['field_name']])){
if ($node->in_preview) {
_taxonomy_fields_widget_invoke('process form values', $node, $field);
}
$result=_taxonomy_fields_field_view($node, $teaser, $page, $field);
if (is_array($result)) {
foreach($result as $item){
$return[$field['field_name']]=$item;
}
}
else if (isset($result)) {
$return[$field['field_name']] = $result;
}
$in_node['fields'][$field['field_name']]=$result;
}
}
}
}
if(is_array($return)){
foreach ($return as $value){
$node->content = array_merge((array) $node->content, $return);
}
}
break;
case 'validate':
foreach ($fields as $tid => $field_term){
if($field_term['ancestors']){
$field_term['fields']=array_merge($field_term['fields'],taxonomy_fields_get_ancestor_fields($tid));
}
if($field_term['fields']){
foreach($field_term['fields'] as $field){
_taxonomy_fields_widget_invoke('validate', $node, $field);
_taxonomy_fields_widget_invoke('process form values', $node, $field);
_taxonomy_fields_field_invoke('validate', $node, $field, $teaser, $page);
_taxonomy_fields_field_invoke_default('validate', $node, $field, $teaser, $page);
}
}
}
break;
case 'submit':
foreach ($fields as $tid => $field_term){
if($field_term['ancestors']){
$field_term['fields']=array_merge($field_term['fields'],taxonomy_fields_get_ancestor_fields($tid));
}
if($field_term['fields']){
foreach($field_term['fields'] as $field){
_taxonomy_fields_widget_invoke('submit', $node, $field);
_taxonomy_fields_widget_invoke('process form values', $node, $field);
_taxonomy_fields_field_invoke('submit', $node, $field, $teaser, $page);
_taxonomy_fields_field_invoke_default('submit', $node, $field, $teaser, $page);
}
}
}
break;
}
}
}
/**
* Invoke a field hook.
*/
function _taxonomy_fields_field_invoke($op, &$node, $field, $teaser = NULL, $page = NULL){
$node_field = isset($node->$field['field_name']) ? $node->$field['field_name'] : array();
$return = array();
$field_types = _taxonomy_fields_field_types();
$module = $field_types[$field['type']]['module'];
$function = $module .'_field';
if (function_exists($function)) {
$result = $function($op, $node, $field, $node_field, $teaser, $page);
if (is_array($result)) {
$return = array_merge($return, $result);
}
else if (isset($result)) {
$return[] = $result;
}
}
// test for values in $node_field in case modules added items on insert
if (isset($node->$field['field_name']) || count($node_field)) {
$node->$field['field_name'] = $node_field;
}
return $return;
}
/**
* Invoke content.module's version of a field hook.
*/
function _taxonomy_fields_field_invoke_default($op, &$node, $field, $teaser = NULL, $page = NULL) {
$return = array();
$node_field = isset($node->$field['field_name']) ? $node->$field['field_name'] : array();
$db_info = module_invoke('content','database_info',$field);
if (count($db_info['columns'])) {
$result = module_invoke('content','field',$op, $node, $field, $node_field, $teaser, $page);
if (is_array($result)) {
$return = array_merge($return, $result);
}
else if (isset($result)) {
$return[] = $result;
}
}
if (isset($node->$field['field_name'])) {
$node->$field['field_name'] = $node_field;
}
return $return;
}
/**
* Invoke a widget hook.
*/
function _taxonomy_fields_widget_invoke($op, &$node, $field) {
$widget_types = _taxonomy_fields_widget_types();
$module = $widget_types[$field['widget']['type']]['module'];
$return = array();
$node_field = isset($node->$field['field_name']) ? $node->$field['field_name'] : array();
$function = $module .'_widget';
if (function_exists($function)) {
$result = $function($op, $node, $field, $node_field);
if (is_array($result) && $op == 'form') {
$result[$field['field_name']]['#weight'] = $field['widget']['weight'];
}
if (is_array($result)) {
$return = array_merge($return, $result);
}
else if (isset($result)) {
$return[] = $result;
}
}
// test for values in $node_field in case modules added items on insert
if (is_object($node) && (isset($node->$field['field_name']) || count($node_field))) {
$node->$field['field_name'] = $node_field;
}
return $return;
}
/**
* Return an array with all fields of ancestors
*/
function taxonomy_fields_get_ancestor_fields($tid){
$field_term=array();
$parents=module_invoke('taxonomy','get_parents_all',$tid);
foreach ($parents as $parent){
if($parent->tid!=$tid){
$terms=taxonomy_fields_terms($parent->tid);
foreach ($terms['fields'] as $term){
$term['term']=$parent->name;
$field_term[]=$term;
}
}
}
return $field_term;
}
/**
* Return a list of all fields of a node
*/
function taxonomy_fields_get_node_info(&$node){
$field=array();
$query=db_query('SELECT tid FROM {term_node} WHERE nid = %d', $node->nid);
while($terms=db_fetch_object($query)){
$term=$terms->tid;
$field[$term]=taxonomy_fields_terms($term);
}
return $field;
}
/**
* Return a list of all terms.
*
* @param $tid
* If set, return information on just this term.
*/
function taxonomy_fields_terms($tid = NULL) {
$info = _taxonomy_fields_term_info();
if (isset($tid)) {
if (isset($info['terms']['term_related_'.$tid])) {
return $info['terms']['term_related_'.$tid];
}
else {
return NULL;
}
}
return $info['terms'];
}
/**
* Return a list of field types.
*/
function _taxonomy_fields_field_types() {
$info = _taxonomy_fields_term_info();
return $info['field types'];
}
/**
* Return a list of widget types.
*/
function _taxonomy_fields_widget_types() {
$info = _taxonomy_fields_term_info();
return $info['widget types'];
}
/**
* Return a list of all fields.
*
* @param $field_name
* If set, return information on just this field.
* @param $tid
* If set, return information of the field within the context of this term.
*
*/
function taxonomy_fields_fields($field_name = NULL, $tid = NULL) {
$info = _taxonomy_fields_term_info();
if (isset($field_name)) {
if (isset($info['fields'][$field_name])) {
if (isset($tid)) {
if (isset($info['terms']['term_related_'.$tid]['fields'][$field_name])) {
return $info['terms']['term_related_'.$tid]['fields'][$field_name];
}
else {
return NULL;
}
}
else {
return $info['fields'][$field_name];
}
}
else {
return NULL;
}
}
return $info['fields'];
}
/**
* Menu callback; present a form for removing a field from a term.
*/
function _taxonomy_fields_edit_field_remove($tid, $field_name) {
$term = taxonomy_fields_terms($tid);
$field = $term['fields'][$field_name];
$form = array();
$form['tid'] = array(
'#type' => 'value',
'#value' => $tid,
);
$form['field_name'] = array(
'#type' => 'value',
'#value' => $field_name,
);
$output = confirm_form($form,
t('Are you sure you want to remove the field %field from the term %term?', array('%field' => $field['widget']['label'], '%term' => $term['name'])),
'admin/content/taxonomy_fields',
t('If you have any content left in this field, it will be lost. This action cannot be undone.'),
t('Remove'), t('Cancel'),
'confirm'
);
return $output;
}
/**
* Remove a field from a term.
*/
function _taxonomy_fields_edit_field_remove_submit($form_id, $form_values) {
$type = taxonomy_fields_terms($form_values['tid']);
$field = $type['fields'][$form_values['field_name']];
if ($type && $field && $form_values['confirm']) {
taxonomy_fields_field_instance_delete($form_values);
drupal_set_message(t('Removed field %field from %type.', array('%field' => $field['widget']['label'], '%type' => $type['name'])));
return 'admin/content/taxonomy_fields';
}
}
/**
* Delete an existing field instance.
*
* @param $instance
* An array of properties to use in selecting a field instance. Valid keys:
* - 'tid' - The name of the term in which the instance exists.
* - 'field_name' - The name of the field whose instance is to be deleted.
*/
function taxonomy_fields_field_instance_delete($instance) {
db_query("DELETE FROM {node_field_instance} WHERE type_name = '%s' AND field_name = '%s'", 'term_related_'.$instance['tid'], $instance['field_name']);
db_query("DELETE FROM {taxonomy_fields} WHERE tid = %d AND field_name = '%s'", $instance['tid'], $instance['field_name']);
$type = taxonomy_fields_terms($instance['tid']);
$field = $type['fields'][$instance['field_name']];
$field_types = _taxonomy_fields_field_types();
$field_type = $field_types[$field['type']];
$columns = module_invoke($field_type['module'], 'field_settings', 'database columns', $field);
$instances = db_result(db_query("SELECT COUNT(*) FROM {node_field_instance} WHERE field_name = '%s'", $instance['field_name']));
// If only one instance remains, we may need to change the database
// representation for this field.
if ($instances == 1) {
if (!($field['multiple'])) {
// Multiple-valued fields are always stored per-content-type.
if (is_array($columns) && count($columns)) {
$new_field = $field;
$new_field['db_storage'] = CONTENT_DB_STORAGE_PER_CONTENT_TYPE;
db_query("UPDATE {node_field} SET db_storage = %d WHERE field_name = '%s'", CONTENT_DB_STORAGE_PER_CONTENT_TYPE, $instance['field_name']);
content_alter_db_field($field, $columns, $new_field, $columns);
}
}
}
// If no instances remain, delete the field entirely.
else if ($instances == 0) {
if (is_array($columns) && count($columns)) {
content_alter_db_field($field, $columns, array(), array());
}
db_query("DELETE FROM {node_field} WHERE field_name = '%s'", $instance['field_name']);
}
//if this was the only field assigned to this term, delete the term table
$result=db_result(db_query("SELECT COUNT(*) FROM {node_field_instance} WHERE type_name = '%s'", 'term_related_'.$instance['tid'] ));
if($result==0){
db_query('DROP TABLE {content_type_term_related_'.$instance['tid'].'}');
}
taxonomy_fields_clear_terms_cache();
}
/**
* Menu callback; presents the field editing page.
*/
function _taxonomy_fields_edit_field($tid, $field_name) {
$term = taxonomy_fields_terms($tid);
$field = $term['fields'][$field_name];
$field_types = _taxonomy_fields_field_types();
$field_type = $field_types[$field['type']];
$widget_types = _taxonomy_fields_widget_types();
$widget_type = $widget_types[$field['widget']['type']];
$form = array();
//field settings for the field with this term
$form['widget'] = array(
'#type' => 'fieldset',
'#title' => t('Widget settings'),
'#description' => t('
These settings apply only to the %field field as it appears in the %type vocabulary term.', array('%field' => $field['widget']['label'], '%type' => $term['name'])),
);
$options = array();
foreach ($widget_types as $possible_widget_name => $possible_widget_type) {
if (in_array($field['type'], $possible_widget_type['field types'])) {
$options[$possible_widget_name] = $possible_widget_type['label'];
}
}
if (count($options) == 1) {
$key = array_keys($options);
$default_widget = array_pop($key);
}
$form['widget']['widget_type'] = array(
'#type' => 'radios',
'#title' => t('Widget'),
'#options' => $options,
'#default_value' => $field['widget']['type'] ? $field['widget']['type'] : $default_widget,
'#required' => TRUE,
);
$form['widget']['label'] = array(
'#type' => 'textfield',
'#title' => t('Label'),
'#default_value' => $field['widget']['label'],
'#required' => TRUE,
);
$form['widget']['weight'] = array(
'#type' => 'weight',
'#title' => t('Weight'),
'#default_value' => $field['widget']['weight'],
'#description' => t('In the node editing form, the heavier fields will sink and the lighter fields will be positioned nearer the top.'),
);
$additions = module_invoke($widget_type['module'], 'widget_settings', 'form', $field['widget']);
if (is_array($additions)) {
$form['widget'] = array_merge($form['widget'], $additions);
}
$form['widget']['description'] = array(
'#type' => 'textarea',
'#title' => t('Help text'),
'#default_value' => $field['widget']['description'],
'#rows' => 5,
'#description' => t('Instructions to present to the user below this field on the editing form.'),
'#required' => FALSE,
);
//default values settings
$handle = module_invoke('content','handle','widget', 'default value', $field);
if ($handle == CONTENT_CALLBACK_DEFAULT) {
$form['#attributes'] = array("enctype" => "multipart/form-data");
$form['widget']['default_value_fieldset'] = array(
'#type' => 'fieldset',
'#title' => t('Default value'),
'#collapsible' => TRUE,
'#collapsed' => TRUE,
);
$default_value = is_array($field['widget']['default_value']) ? $field['widget']['default_value'] : array();
$module = $widget_types[$field['widget']['type']]['module'];
$function = $module .'_widget';
if (function_exists($function)) {
$node = array(); // TODO are there things we need to add in here ?
// Make sure the default value is not a required field.
$widget_field = $field;
$widget_field['required'] = FALSE;
$function('prepare form values', $node, $widget_field, $default_value);
$form_element = $function('form', $node, $widget_field, $default_value);
}
else {
// TODO : generate a series of textfields ?
// why would a widget not have a hook_widget implementation ?
}
$form['widget']['default_value_fieldset']['default_value_widget'] = $form_element;
$form['widget']['default_value_fieldset']['default_value_widget']['#tree'] = TRUE;
$form['widget']['default_value_fieldset']['advanced_options'] = array(
'#type' => 'fieldset',
'#title' => t('Php code'),
'#collapsible' => TRUE,
'#collapsed' => empty($field['widget']['default_value_php']),
);
$db_info = module_invoke('content','database_info',$field);
$columns = array_keys($db_info['columns']);
foreach ($columns as $key => $column) {
$columns[$key] = "'$column' => ...";
}
$sample = 'array( 0 => array('. implode(', ', $columns) .'), 1 => ...)';
$form['widget']['default_value_fieldset']['advanced_options']['default_value_php'] = array(
'#type' => 'textarea',
'#title' => t('Code'),
'#default_value' => $field['widget']['default_value_php'],
'#rows' => 6,
'#tree' => TRUE,
'#description' => t('Advanced Usage Only: PHP code that returns a default value. Should not include <?php ?> delimiters.
If this field is filled out, the value returned by this code will override any value in the textfield above.
Expected format : @sample.', array('@sample' => $sample)),
);
}
//field universal settings
if($field_type['label']!='Image' && $field_type['label']!='file'){
$form['widget']['uni'] = array(
'#type' => 'fieldset',
'#title' => t('Universal field value settings'),
'#description' => t('
Here you can give the field a value which will be always displayed'),
);
$form['widget']['uni']['universal'] = array(
'#type' => 'checkbox',
'#title' => t('Universal'),
'#default_value' => $field['universal'],
'#description' => t('All %field fields will have the same value for the %type term.',array('%field' => $field['widget']['label'], '%type' => $term['name'])),
);
$node_field=array();
if($field['universal']){
$query=db_query('SELECT field_value,delta FROM {taxonomy_fields} WHERE field_name="%s" AND universal=1 AND tid=%d', $field['field_name'],$tid);
while($result=db_fetch_object($query)){
$node_field[$result->delta]=unserialize($result->field_value);
}
}
$module = $widget_types[$field['widget']['type']]['module'];
$function = $module .'_widget';
if (function_exists($function)) {
$function('prepare form values', $node, $field, $node_field);
$result = $function('form', $node, $field, $node_field);
if (is_array($result)) {
$result[$field['field_name']]['#weight'] = $field['widget']['weight'];
}
}
//change name to differ from default_values
$result[$field['field_name'].'_']=$result[$field['field_name']];
unset($result[$field['field_name']]);
$form['widget']['uni']['universal_value']=$result;
}
//global field settings
$form['field'] = array(
'#type' => 'fieldset',
'#title' => t('Data settings'),
'#description' => t('These settings apply to the %field field in every content type and term in which it appears.', array('%field' => $field['widget']['label'])),
);
$form['field']['required'] = array(
'#type' => 'checkbox',
'#title' => t('Required'),
'#default_value' => $field['required'],
);
$form['field']['multiple'] = array(
'#type' => 'checkbox',
'#title' => t('Multiple values'),
'#default_value' => $field['multiple'],
);
$additions = module_invoke($field_type['module'], 'field_settings', 'form', $field);
if (is_array($additions)) {
$form['field'] = array_merge($form['field'], $additions);
}
$form['submit'] = array(
'#type' => 'submit',
'#value' => t('Save field settings'),
);
$form['tid'] = array(
'#type' => 'value',
'#value' => $term['tid'],
);
$form['field_name'] = array(
'#type' => 'value',
'#value' => $field_name,
);
$form['#attributes'] = array("enctype" => "multipart/form-data");
return $form;
}
/**
* Validate a field's settings.
*/
function _taxonomy_fields_edit_field_validate($form_id, $form_values) {
$type = taxonomy_fields_terms($form_values['tid']);
$field = $type['fields'][$form_values['field_name']];
$field_types = _taxonomy_fields_field_types();
$field_type = $field_types[$field['type']];
$widget_types = _taxonomy_fields_widget_types();
$widget_type = $widget_types[$field['widget']['type']];
$field_function = $field_type['module'] .'_field';
$widget_function = $widget_type['module'] .'_widget';
if($form_values['universal']){
$uni_value=$form_values[$form_values['field_name'].'_'];
if (function_exists($widget_function)) {
$widget_function('validate', $node, $field, $uni_value);
$widget_function('process form values', $node, $field, $uni_value);
form_set_value(array('#parents' => array($form_values['field_name'].'_')), $uni_value);
}
if (function_exists($field_function)) {
$field_function('validate', $node, $field, $uni_value, $teaser, $page);
}
$form=form_get_errors();
if (!empty($form)){
return 'admin/content/taxonomy_fields/'.$form_values['tid'].'/fields/'.$form_values['field_name'];
}
//validate number fields because number.module does not validate on value-format
elseif($form_values['widget_type']=='number'){
foreach ($uni_value as $key =>$value){
if($value['value'] && !is_numeric($value['value'])){
$uni_value[$key]['value']=0;
}
}
form_set_value(array('#parents' => array($form_values['field_name'].'_')), $uni_value);
}
}
module_invoke($widget_type['module'], 'widget_settings', 'validate', array_merge($field, $form_values));
module_invoke($field_type['module'], 'field_settings', 'validate', array_merge($field, $form_values));
// If content.module is handling the default value,
// validate the result using the field validation.
$handle=module_invoke('content','handle','widget', 'default value', $field);
if ($handle == CONTENT_CALLBACK_DEFAULT) {
if (isset($form_values['default_value_php']) && ($php = trim($form_values['default_value_php']))) {
ob_start();
$return = eval($php);
ob_end_clean();
if (!is_array($return)) {
$error = TRUE;
}
else {
foreach ($return as $item) {
if (!is_array($item)) {
$error = TRUE;
break;
}
}
}
if ($error) {
$db_info = module_invoke('content','database_info',$field);
$columns = array_keys($db_info['columns']);
foreach ($columns as $key => $column) {
$columns[$key] = "'$column' => ...";
}
$sample = 'array( 0 => array('. implode(', ', $columns) .'), 1 => ...)';
form_set_error('default_value_php', t('The default value php code returned an incorrect value
Expected format : @sample
Returned value : @value', array('@sample' => $sample, '@value' => print_r($return, true))));
return;
}
else {
$default_value = $return;
$is_code = TRUE;
form_set_value(array('#parents' => array('default_value_php')), $php);
form_set_value(array('#parents' => array('default_value')), array());
}
}
else {
$default_value = $form_values['default_value_widget'][$field['field_name']];
$is_code = FALSE;
form_set_value(array('#parents' => array('default_value_php')), '');
form_set_value(array('#parents' => array('default_value')), $default_value);
}
if (isset($default_value)) {
$node = array();
$node[$form_values['field_name']] = $default_value;
$field['required'] = FALSE;
// If default_value is created from php code, don't run it through widget processing.
// This way the default value code can directly create the correct array without being
// mangled by widget processing which sometimes requires an input array in a completely different format.
if (function_exists($widget_function) && !$is_code) {
$widget_function('validate', $node, $field, $default_value);
$widget_function('process form values', $node, $field, $default_value);
// The widget processing may have altered the value, save it to be sure.
form_set_value(array('#parents' => array('default_value')), $default_value);
}
if (function_exists($field_function)) {
$field_function('validate', $node, $field, $default_value, NULL, NULL);
}
// The field validation routine won't set an error on the right field, so set it here.
if (form_get_errors()) {
if (trim($form_values['default_value_php'])) {
form_set_error('default_value_php', t('The default value php code created @value which is invalid.', array('@value' => print_r($default_value, true))));
}
else {
form_set_error('default_value', t('The default value is invalid.'));
}
}
}
}
}
/**
* Save a field's settings after editing.
*/
function _taxonomy_fields_edit_field_submit($form_id, $form_values) {
$term = taxonomy_fields_terms($form_values['tid']);
$field = $term['fields'][$form_values['field_name']];
$field_types = _taxonomy_fields_field_types();
$field_type = $field_types[$field['type']];
$widget_types = _taxonomy_fields_widget_types();
$widget_type = $widget_types[$form_values['widget_type']];
$widget_settings = array();
// If content.module is handling the default value,
// initialize $widget_settings with default values,
$handle=module_invoke('content','handle','widget', 'default value', $field);
if ($handle == CONTENT_CALLBACK_DEFAULT) {
$widget_settings = array(
'default_value' => $form_values['default_value'],
'default_value_php' => $form_values['default_value_php'],
);
}
$setting_names = module_invoke($widget_type['module'], 'widget_settings', 'save', $field);
if (is_array($setting_names)) {
foreach ($setting_names as $setting) {
$widget_settings[$setting] = $form_values[$setting];
}
}
$field_settings = array();
$setting_names = module_invoke($field_type['module'], 'field_settings', 'save', $field);
if (is_array($setting_names)) {
foreach ($setting_names as $setting) {
$field_settings[$setting] = $form_values[$setting];
}
}
$prev_field = $field;
$prev_columns = module_invoke($field_type['module'], 'field_settings', 'database columns', $field);
db_query("UPDATE {node_field_instance} SET weight = %d, label = '%s', widget_type = '%s', widget_settings = '%s', description = '%s' WHERE type_name = '%s' AND field_name = '%s'", $form_values['weight'], $form_values['label'], $form_values['widget_type'], serialize($widget_settings), $form_values['description'], 'term_related_'.$form_values['tid'], $form_values['field_name']);
if ($form_values['multiple']) {
$field['db_storage'] = 0;
}
else {
$instances = db_result(db_query("SELECT COUNT(*) FROM {node_field_instance} WHERE field_name = '%s'", $form_values['field_name']));
if ($instances == 1) {
$field['db_storage'] = 1;
}
}
db_query("UPDATE {node_field} SET required = %d, multiple = %d, global_settings = '%s', db_storage = %d WHERE field_name = '%s'", $form_values['required'], $form_values['multiple'], serialize($field_settings), $field['db_storage'], $form_values['field_name']);
drupal_set_message(t('Saved field %field assigned to the %term term.', array('%field' => $form_values['label'], '%term' => $term['name'])));
taxonomy_fields_clear_terms_cache();
$new_field = taxonomy_fields_fields($form_values['field_name']);
$new_columns = module_invoke($field_type['module'], 'field_settings', 'database columns', $new_field);
if (!isset($prev_columns)) {
$prev_columns = array();
}
if (!isset($new_columns)) {
$new_columns = array();
}
content_alter_db_field($prev_field, $prev_columns, $new_field, $new_columns);
if($form_values['universal'] && is_array($form_values[$form_values['field_name'].'_'])){
db_query('DELETE FROM {taxonomy_fields} WHERE field_name="%s" AND tid=%d', $form_values['field_name'], $form_values['tid']);
foreach ($form_values[$form_values['field_name'].'_'] as $key => $value){
db_query('INSERT INTO {taxonomy_fields}(field_name, field_value, tid, delta, universal) VALUES ("%s","%s",%d,%d,%d)', $form_values['field_name'], $value ? serialize($value) : '', $form_values['tid'], $key, 1);
}
}
else {
db_query('DELETE FROM {taxonomy_fields} WHERE field_name="%s" AND tid=%d', $form_values['field_name'], $form_values['tid']);
db_query('INSERT INTO {taxonomy_fields}(field_name, field_value, tid, delta, universal) VALUES ("%s","%s",%d,%d,%d)', $form_values['field_name'], '', $form_values['tid'], 0, 0);
}
taxonomy_fields_clear_terms_cache();
return 'admin/content/taxonomy_fields';
}
/**
* Collate all information on terms, fields, and related structures.
*
* @param $reset
* If TRUE, clear the cache and fetch the information from the database again.
*/
function _taxonomy_fields_term_info($reset = FALSE) {
static $info;
if ($reset || !isset($info)) {
if ($cached = cache_get('taxonomy_fields_term_info', 'cache_content')) {
$info = unserialize($cached->data);
}
else {
$info = array(
'field types' => array(),
'widget types' => array(),
'fields' => array(),
'terms' => array(),
);
foreach (module_list() as $module) {
$module_field_types = module_invoke($module, 'field_info');
if ($module_field_types) {
foreach ($module_field_types as $name => $field_info) {
$info['field types'][$name] = $field_info;
$info['field types'][$name]['module'] = $module;
$info['field types'][$name]['formatters'] = array();
}
}
$module_widgets = module_invoke($module, 'widget_info');
if ($module_widgets) {
foreach ($module_widgets as $name => $widget_info) {
$info['widget types'][$name] = $widget_info;
$info['widget types'][$name]['module'] = $module;
}
}
}
foreach (module_list() as $module) {
$module_formatters = module_invoke($module, 'field_formatter_info');
if ($module_formatters) {
foreach ($module_formatters as $name => $formatter_info) {
foreach ($formatter_info['field types'] as $field_type) {
$info['field types'][$field_type]['formatters'][$name] = $formatter_info;
$info['field types'][$field_type]['formatters'][$name]['module'] = $module;
}
}
}
}
$field_result = db_query('SELECT * FROM {node_field} nf');
while ($field = db_fetch_array($field_result)) {
$global_settings = $field['global_settings'] ? unserialize($field['global_settings']) : array();
unset($field['global_settings']);
$field = array_merge($field, $global_settings);
$instance_info = db_fetch_array(db_query("SELECT type_name, label FROM {node_field_instance} WHERE field_name = '%s'", $field['field_name']));
$field['widget']['label'] = $instance_info['label'];
$field['type_name'] = $instance_info['type_name'];
$info['fields'][$field['field_name']] = $field;
}
$term_result = db_query('SELECT *,td.tid AS tid FROM {term_data} td LEFT JOIN {taxonomy_fields_ancestors} tfa ON td.tid=tfa.tid ORDER BY td.tid ASC');
while ($term = db_fetch_array($term_result)) {
$term['fields'] = array();
$field_result = db_query("SELECT v.value, nfi.field_name, nfi.weight, nfi.label, nfi.widget_type, nfi.widget_settings, nfi.display_settings, nfi.description FROM {node_field_instance} nfi LEFT JOIN {variable} v ON v.name = '%s' WHERE nfi.type_name = '%s' AND v.value = '%s' ORDER BY nfi.weight ASC, nfi.label ASC", 'tax_fields_voc_'.$term['vid'], 'term_related_'.$term['tid'], 's:1:"1";');
while ($field = db_fetch_array($field_result)) {
// Overwrite global field information with specific information
$field = array_merge($info['fields'][$field['field_name']], $field);
variable_set('tax_vid',$field['value']);
$widget_settings = $field['widget_settings'] ? unserialize($field['widget_settings']) : array();
unset($field['widget_settings']);
$field['widget'] = $widget_settings;
$field['widget']['type'] = $field['widget_type'];
unset($field['widget_type']);
$field['widget']['weight'] = $field['weight'];
unset($field['weight']);
$field['widget']['label'] = $field['label'];
unset($field['label']);
$field['widget']['description'] = $field['description'];
unset($field['description']);
$field['type_name'] = 'term_related_'.$term['tid'];
$field['display_settings'] = $field['display_settings'] ? unserialize($field['display_settings']) : array();
$result=db_fetch_object(db_query('SELECT tf.universal FROM {taxonomy_fields} tf WHERE tf.tid=%d AND tf.field_name="%s"',$term['tid'],$field['field_name']));
$field['universal']=$result->universal;
$term['fields'][$field['field_name']] = $field;
}
$info['terms']['term_related_'.$term['tid']] = $term;
}
cache_set('taxonomy_fields_term_info', 'cache_content', serialize($info));
}
}
return $info;
}
/**
* Clear the cache of terms; called in several places when taxonomy fields
* information is changed.
*/
function taxonomy_fields_clear_terms_cache() {
module_invoke('content','clear_type_cache');
cache_clear_all('taxonomy_fields_term_info', 'cache_content');
_taxonomy_fields_term_info(TRUE);
}
/**
* Format field output based on display settings.
*/
function _taxonomy_fields_field_view(&$node, $teaser=NULL, $page=NULL, $field) {
$field_types = _taxonomy_fields_field_types();
$context = $teaser ? 'teaser' : 'full';
$return = array();
$node_field = isset($node->$field['field_name']) ? $node->$field['field_name'] : array();
$formatter = isset($field['display_settings'][$context]['format']) ? $field['display_settings'][$context]['format'] : 'default';
$value = '';
if ($formatter != 'hidden') {
$handle=module_invoke('content','handle','field', 'view', $field);
if ($handle == CONTENT_CALLBACK_CUSTOM) {
$module = $field_types[$field['type']]['module'];
$function = $module .'_field';
if (function_exists($function)) {
$value = $function('view', $node, $field, $node_field, $teaser, $page);
}
}
else {
foreach ($node_field as $delta => $item) {
$node_field[$delta]['view'] = module_invoke('content','format',$field, $item, $formatter, $node);
}
$value = theme('field', $node, $field, $node_field, $teaser, $page);
}
if(empty($value) && $handle==CONTENT_CALLBACK_DEFAULT){
$value_old=_taxonomy_fields_field_invoke('view',$node, $field, $node_field, $teaser, $page);
if(!empty($value_old) && is_array($value_old)){
foreach ($value_old as $old){
$value.=$old;
}
}
}
}
$return[$field['field_name']] = array(
'#weight' => $field['widget']['weight'],
'#value' => $value,
'#access' => $formatter != 'hidden',
);
// test for values in $node_field in case modules added items
if (isset($node->$field['field_name']) || count($node_field)) {
$node->$field['field_name'] = $node_field;
}
return $return;
}
/**
* Menu callback; presents a listing of fields display settings for a term.
*
* Form includes form widgets to select which fields appear for teaser, full node...
* and how the field labels should be rendered
*/
function taxonomy_fields_display_overview_form() {
$tid=arg(3);
$term = taxonomy_fields_terms($tid);
$field_types = _taxonomy_fields_field_types();
$form = array();
if (empty($term['fields'])) {
drupal_set_message(t('There are no fields configured for this term.'));
return '';
}
$form['#tree'] = TRUE;
foreach ($term['fields'] as $field) {
$form['fields'][$field['field_name']] = _content_admin_display_overview_row($field, $field_types[$field['type']]);
}
$form['tid'] = array('#type' => 'hidden', '#value' => $term['tid']);
$form['submit'] = array('#type' => 'submit', '#value' => t('Submit'));
return $form;
}
function taxonomy_fields_display_overview_form_submit($form_id, $form_values) {
$tid=$form_values['tid'];
foreach ($form_values['fields'] as $fieldname => $fieldvalues) {
$display_settings = array();
foreach ($fieldvalues as $key => $value) {
$display_settings[$key] = $value;
}
db_query("UPDATE {node_field_instance} SET display_settings = '%s' WHERE type_name = '%s' AND field_name = '%s'",
serialize($display_settings), 'term_related_'.$tid, $fieldname);
}
drupal_set_message(t('Your settings have been saved.'));
taxonomy_fields_clear_terms_cache();
}
/**
* Implementation of hook_taxonomy().
*/
function taxonomy_fields_taxonomy($op, $type, $array = array()) {
if ($type == 'vocabulary') {
if($op == 'delete') {
variable_del('tax_fields_voc_'.$array['vid']);
}
else {
variable_set('tax_fields_voc_'.$array['vid'], $array['tax_fields']);
}
}
taxonomy_fields_clear_terms_cache();
}
/**
* Theme the field overview table by iterating through the form and rendering form elements in table cells
*/
function theme_taxonomy_fields_display_overview_form($form) {
$header = array(t('Field'), t('Type'), t('Label'));
foreach (_content_admin_display_contexts() as $key => $title) {
$header[] = $title;
}
$rows = array();
foreach (element_children($form['fields']) as $field) {
$row = array();
foreach (element_children($form['fields'][$field]) as $key) {
$row[] = drupal_render($form['fields'][$field][$key]);
}
$rows[] = $row;
}
$output = theme('table', $header, $rows, array('class' => 'taxonomy_fields-field-display-overview'));
$output .= drupal_render($form);
return $output;
}
/**
* Theme the list of terms and their fields used by taxonomy_fields
function theme_taxonomy_fields_list_output($field_output){
$header= array(t('Label'), t('Name'), t('Field type'), t('Widget type'), t('Weight'), t('Universal'), array('data' => t('Operations'), 'colspan' => 2));
foreach ($field_output as $key => $value){
$output.='
'.$value['name'].'
';
if($value['ancestors']){
$output.='(ancestors enabled)
';
}
$output.=''.l(t('terms settings'),'admin/content/taxonomy_fields/'.$key);
$output.=' ';
$output.=l(t('display settings'),'admin/content/taxonomy_fields/'.$key.'/fields').'
';
$output.=theme('table',$header,$value['rows']);
}
return $output;
}
*/
function theme_taxonomy_fields_list_output($field_output) {
$output = '';
$header= array(t('Label'), t('Name'), t('Field type'), t('Widget type'), t('Weight'), t('Universal'), array('data' => t('Operations'), 'colspan' => 2));
$root_terms = array();
foreach ($field_output as $key => $value) {
if (!empty($value['parent'])) {
$field_output[$key]['rows'] = array_merge($field_output[$key]['rows'], _taxonomy_fields_list_ancestors_rows($field_output, $key));
$field_output['children'][$value['parent']][] = $key;
}
else {
$root_terms[$value['vid']][] = $key;
}
}
foreach ($root_terms as $vid => $terms) {
$voc = taxonomy_get_vocabulary($vid);
$output .= ''. $voc->name ."
\n";
$link = array(
array(
'title' => t('Edit vocabulary'),
'href' => 'admin/content/taxonomy/edit/vocabulary/'. $vid,
),
);
$output .= theme('links', $link);
$output .= '';
foreach ($terms as $tid) {
$output .= theme('taxonomy_fields_list_term', $field_output, $tid);
}
$output .= "
\n";
}
return $output;
}
function _taxonomy_fields_list_ancestors_rows($field_output, $tid) {
$rows = array();
$parent_tid = $field_output[$tid]['parent'];
if (!empty($field_output[$parent_tid]['rows']) && $field_output[$tid]['ancestors']) {
foreach ($field_output[$parent_tid]['rows'] as $field_name => $cols) {
$cols[6] = array('data' => ''. t('inherited') .'', 'colspan' => 2);
unset($cols[7]);
$rows[$field_name] = $cols;
}
}
if (!empty($field_output[$parent_tid]['parent'])) {
$rows = array_merge($rows, _taxonomy_fields_list_ancestors_rows($field_output, $field_output[$parent_tid]['parent']));
}
return $rows;
}
function theme_taxonomy_fields_list_term($field_output, $tid) {
$output .= ''. $field_output[$tid]['name'] . ($field_output[$tid]['ancestors'] ? ' ('. t('ancestors enabled') .')' : '') ."
\n";
$links = array(
array(
'title' => t('Terms settings'),
'href' => 'admin/content/taxonomy_fields/'. $tid,
),
array(
'title' => t('Display settings'),
'href' => 'admin/content/taxonomy_fields/'. $tid. '/fields',
),
);
$output .= theme('links', $links);
$output .= theme('table', $header, $field_output[$tid]['rows']);
if (isset($field_output['children']) && isset($field_output['children'][$tid])) {
$output .= "\n";
foreach ($field_output['children'][$tid] as $child_id) {
$output .= theme('taxonomy_fields_list_term', $field_output, $child_id);
}
$output .= "
\n";
}
return $output;
}
function theme_taxonomy_fields_field_add_new_field_widget_type($form) {
$field_types = _taxonomy_fields_field_types();
$widget_types = _taxonomy_fields_widget_types();
$output = '';
$output .= '';
foreach ($field_types as $field_name => $field_type) {
$output .= '- '. $field_type['label'] .'
';
foreach ($widget_types as $widget_name => $widget_type) {
if (in_array($field_name, $widget_type['field types'])) {
$output .= '- '. drupal_render($form[$field_name .'-'. $widget_name]) .'
';
}
}
}
$output .= '
';
return $output;
}
?>