all contrib module security updates done

This commit is contained in:
2020-09-24 22:47:32 +02:00
parent 7d87153100
commit 0fbb9c4610
1612 changed files with 116663 additions and 32269 deletions
@@ -2,7 +2,7 @@
.block .field-widget-term-reference-tree ul,
.field-widget-term-reference-tree ul
{
list-style-type: none;
list-style-type: none;
margin-top: 0;
margin-bottom: 0;
margin-left: 0;
@@ -113,14 +113,18 @@
* Styles for display element
*/
.field-widget-term-reference-tree .selected {
.term-tree-list .selected {
font-weight: bold;
}
.field-widget-term-reference-tree .unselected {
.term-tree-list .unselected {
font-weight: normal;
}
.field-widget-term-reference-tree ul {
.term-tree-list ul {
margin-top: 0;
}
.field-type-taxonomy-term-reference ul.links .term-tree-list ul.term li {
float: none;
}
@@ -25,12 +25,14 @@ function term_reference_tree_field_formatter_view($entity_type, $entity, $field,
switch ($display['type']) {
case 'term_reference_tree':
$element[] = array(
'#theme' => 'term_tree_list',
'#data' => $items,
'#display' => $display,
'#attached' => array('css' => array(drupal_get_path('module', 'term_reference_tree') . '/term_reference_tree.css')),
);
if (!empty($items)) {
$element[] = array(
'#theme' => 'term_tree_list',
'#data' => $items,
'#display' => $display,
'#attached' => array('css' => array(drupal_get_path('module', 'term_reference_tree') . '/term_reference_tree.css')),
);
}
break;
}
@@ -66,7 +68,7 @@ function term_reference_tree_field_formatter_settings_form($field, $instance, $v
'#token_types' => array('term'),
);
}
return $element;
}
@@ -81,9 +83,8 @@ function term_reference_tree_field_formatter_settings_summary($field, $instance,
$summary = '';
if ($display['type'] == 'term_reference_tree') {
$summary = t('Uses tokens: ') . t($settings['token_display_selected'] != '' ? 'Yes' : 'No');
$summary = t('Uses tokens: ') . ($settings['token_display_selected'] != '' ? t('Yes') : t('No'));
}
return $summary;
}
@@ -1,13 +1,12 @@
name = Term Reference Tree
description = An expanding/collapsing tree widget for selecting terms in a taxonomy term reference field
package = Other
description = An expanding/collapsing tree widget for selecting terms in a taxonomy term reference field.
package = Fields
core = 7.x
dependencies[] = taxonomy
; Information added by drupal.org packaging script on 2012-03-26
version = "7.x-1.9"
; Information added by Drupal.org packaging script on 2018-01-31
version = "7.x-1.11"
core = "7.x"
project = "term_reference_tree"
datestamp = "1332793846"
datestamp = "1517382184"
@@ -1,287 +1,292 @@
(function($) {
Drupal.behaviors.termReferenceTree = {
attach: function(context, settings) {
// Bind the term expand/contract button to slide toggle the list underneath.
$('.term-reference-tree-button', context).click(function() {
$(this).toggleClass('term-reference-tree-collapsed');
$(this).siblings('ul').slideToggle('fast');
/**
* Attaches the tree behavior to the term widget form.
*/
Drupal.behaviors.termReferenceTree = {
attach: function(context, settings) {
// Bind the term expand/contract button to slide toggle the list underneath.
$('.term-reference-tree-button', context).once('term-reference-tree-button').click(function() {
$(this).toggleClass('term-reference-tree-collapsed');
$(this).siblings('ul').slideToggle('fast');
});
// An expand all button (unimplemented)
/*
$('.expandbutton').click(function() {
$(this).siblings('.term-reference-tree-button').trigger('click');
});
*/
$('.term-reference-tree', context).once('term-reference-tree', function() {
// On page load, check whether the maximum number of choices is already selected.
// If so, disable the other options.
var tree = $(this);
checkMaxChoices(tree, false);
$(this).find('input[type=checkbox]').change(function() {
checkMaxChoices(tree, $(this));
});
// An expand all button (unimplemented)
/*
$('.expandbutton').click(function() {
$(this).siblings('.term-reference-tree-button').trigger('click');
});
*/
//On page load, check if the user wants a track list. If so, add the
//currently selected items to it.
if($(this).hasClass('term-reference-tree-track-list-shown')) {
var track_list_container = $(this).find('.term-reference-tree-track-list');
//Var to track whether using checkboxes or radio buttons.
var input_type =
( $(this).has('input[type=checkbox]').size() > 0 ) ? 'checkbox' : 'radio';
$('.term-reference-tree', context).each(function() {
// On page load, check whether the maximum number of choices is already selected.
// If so, disable the other options.
var tree = $(this);
checkMaxChoices(tree, false);
$(this).find('input[type=checkbox]').change(function() {
checkMaxChoices(tree, $(this));
//Find all the checked controls.
var checked_controls = $(this).find('input[type=' + input_type + ']:checked');
//Get their labels.
var labels = checked_controls.next();
var label_element;
//For each label of the checked boxes, add item to the track list.
labels.each(function(index) {
label_element = $(labels[index]);
addItemToTrackList(
track_list_container, //Where to add new item.
label_element.html(), //Text of new item.
$(label_element).attr('for'), //Id of control new item is for.
input_type //checkbox or radio
);
}); //End labels.each
//Show "nothing selected" message, if needed.
showNothingSelectedMessage(track_list_container);
//Event - when an element on the track list is clicked on:
// 1. Delete it.
// 2. Uncheck the associated checkbox.
//The event is bound to the track list container, not each element.
$(track_list_container).click(function(event){
//Remove the "nothing selected" message if showing - add it later if needed.
//removeNothingSelectedMessage(track_list_container);
var event_target = $(event.target);
var control_id = event_target.data('control_id');
if(control_id) {
event_target.remove();
var checkbox = $('#' + control_id);
checkbox.removeAttr('checked');
checkMaxChoices(tree, checkbox);
//Show "nothing selected" message, if needed.
showNothingSelectedMessage(track_list_container);
}
});
//On page load, check if the user wants a track list. If so, add the
//currently selected items to it.
if($(this).hasClass('term-reference-tree-track-list-shown')) {
var track_list_container = $(this).find('.term-reference-tree-track-list');
//Var to track whether using checkboxes or radio buttons.
var input_type =
( $(this).has('input[type=checkbox]').size() > 0 ) ? 'checkbox' : 'radio';
//Find all the checked controls.
var checked_controls = $(this).find('input[type=' + input_type + ']:checked');
//Get their labels.
var labels = checked_controls.next();
var label_element;
//For each label of the checked boxes, add item to the track list.
labels.each(function(index) {
label_element = $(labels[index]);
//Change track list when controls are clicked.
$(this).find('.form-' + input_type).change(function(event){
//Remove the "nothing selected" message if showing - add it later if needed.
removeNothingSelectedMessage(track_list_container);
var event_target = $(event.target);
var control_id = event_target.attr('id');
if ( event_target.attr('checked') ) {
//Control checked - add item to the track list.
label_element = event_target.next();
addItemToTrackList(
track_list_container, //Where to add new item.
label_element.html(), //Text of new item.
$(label_element).attr('for'), //Id of control new item is for.
input_type //checkbox or radio
);
}); //End labels.each
}
else {
//Checkbox unchecked. Remove from the track list.
$('#' + control_id + '_list').remove();
}
//Show "nothing selected" message, if needed.
showNothingSelectedMessage(track_list_container);
//Event - when an element on the track list is clicked on:
// 1. Delete it.
// 2. Uncheck the associated checkbox.
//The event is bound to the track list container, not each element.
$(track_list_container).click(function(event){
//Remove the "nothing selected" message if showing - add it later if needed.
//removeNothingSelectedMessage(track_list_container);
var event_target = $(event.target);
var control_id = event_target.data('control_id');
}); //End process checkbox changes.
} //End Want a track list.
if(control_id) {
event_target.remove();
//On page load, check if the user wants a cascading selection.
if($(this).hasClass('term-reference-tree-cascading-selection')) {
var checkbox = $('#' + control_id);
checkbox.removeAttr('checked');
checkMaxChoices(tree, checkbox);
//Show "nothing selected" message, if needed.
showNothingSelectedMessage(track_list_container);
//Check children when checkboxes are clicked.
$(this).find('.form-checkbox').change(function(event) {
var event_target = $(event.target);
var control_id = event_target.attr('id');
var children = event_target.parent().next().children().children('div.form-type-checkbox').children('input[id^="' + control_id + '-children"]');
if(event_target.attr('checked')) {
//Checkbox checked - check children if none were checked.
if(!$(children).filter(':checked').length) {
$(children).click().trigger('change');
}
});
//Change track list when controls are clicked.
$(this).find('.form-' + input_type).change(function(event){
//Remove the "nothing selected" message if showing - add it later if needed.
removeNothingSelectedMessage(track_list_container);
var event_target = $(event.target);
var control_id = event_target.attr('id');
if ( event_target.attr('checked') ) {
//Control checked - add item to the track list.
label_element = event_target.next();
addItemToTrackList(
track_list_container, //Where to add new item.
label_element.html(), //Text of new item.
$(label_element).attr('for'), //Id of control new item is for.
input_type //checkbox or radio
);
}
else {
//Checkbox unchecked. Uncheck children if all were checked.
if(!$(children).not(':checked').length) {
$(children).click().trigger('change');
}
else {
//Checkbox unchecked. Remove from the track list.
$('#' + control_id + '_list').remove();
}
//Show "nothing selected" message, if needed.
showNothingSelectedMessage(track_list_container);
}); //End process checkbox changes.
} //End Want a track list.
//On page load, check if the user wants a cascading selection.
if($(this).hasClass('term-reference-tree-cascading-selection')) {
}
//Check children when checkboxes are clicked.
$(this).find('.form-checkbox').change(function(event) {
var event_target = $(event.target);
var control_id = event_target.attr('id');
var children = event_target.parent().next().children().children('div.form-type-checkbox').children('input[id^="' + control_id + '-children"]');
if(event_target.attr('checked')) {
//Checkbox checked - check children if none were checked.
if(!$(children).filter(':checked').length) {
$(children).click().trigger('change');
}
}
else {
//Checkbox unchecked. Uncheck children if all were checked.
if(!$(children).not(':checked').length) {
$(children).click().trigger('change');
}
}
});
//End process checkbox changes.
} //End Want a cascading checking.
});
//End process checkbox changes.
} //End Want a cascading checking.
});
}
};
/**
* Add a new item to the track list.
* If more than one item can be selected, the new item is positioned to
* match the order of the terms in the checkbox tree.
*
* @param track_list_container Container where the new item will be added.
*
* @param item_text Text of the item to add.
*
* @param control_id Id of the checkbox/radio control the item matches.
*
* @param control_type Control type - 'checkbox' or 'radio'.
*/
function addItemToTrackList(track_list_container, item_text, control_id, control_type) {
var new_item = $('<li class="track-item">' + item_text + '</li>');
new_item.data('control_id', control_id);
//Add an id for easy finding of the item.
new_item.attr('id', control_id + '_list');
//Process radio controls - only one item can be selected.
if ( control_type == 'radio') {
//Find the existing element on the track list, if there is one.
var current_items = track_list_container.find('li');
//If there are no items on the track list, add the new item.
if ( current_items.size() == 0 ) {
track_list_container.append(new_item);
}
else {
//There is an item on the list.
var current_item = $(current_items.get(0));
//Is the item we want to add different from what is there?
if ( current_item.data('control_id') != control_id ) {
//Remove exiting element from track list, and add the new one.
current_item.remove();
track_list_container.append(new_item);
}
}
return;
}
//Using checkboxes, so there can be more than one selected item.
//Find the right place to put the new item, to match the order of the
//checkboxes.
var list_items = track_list_container.find('li');
var item_comparing_to;
//Flag to tell whether the item was inserted.
var inserted_flag = false;
list_items.each(function(index){
item_comparing_to = $(list_items[index]);
//If item is already on the track list, do nothing.
if ( control_id == item_comparing_to.data('control_id') ) {
inserted_flag = true;
return false; //Returning false stops the loop.
}
else if ( control_id < item_comparing_to.data('control_id') ) {
//Add it here.
item_comparing_to.before(new_item);
inserted_flag = true;
return false; //Returning false stops the loop.
}
});
//If not inserted yet, add new item at the end of the track list.
if ( ! inserted_flag ) {
}
};
/**
* Add a new item to the track list.
* If more than one item can be selected, the new item is positioned to
* match the order of the terms in the checkbox tree.
*
* @param track_list_container Container where the new item will be added.
*
* @param item_text Text of the item to add.
*
* @param control_id Id of the checkbox/radio control the item matches.
*
* @param control_type Control type - 'checkbox' or 'radio'.
*/
function addItemToTrackList(track_list_container, item_text, control_id, control_type) {
var new_item = $('<li class="track-item">' + item_text + '</li>');
new_item.data('control_id', control_id);
//Add an id for easy finding of the item.
new_item.attr('id', control_id + '_list');
//Process radio controls - only one item can be selected.
if ( control_type == 'radio') {
//Find the existing element on the track list, if there is one.
var current_items = track_list_container.find('li');
//If there are no items on the track list, add the new item.
if ( current_items.size() == 0 ) {
track_list_container.append(new_item);
}
}
/**
* Show the 'nothing selected' message if it applies.
*
* @param track_list_container Where the message is to be shown.
*/
function showNothingSelectedMessage(track_list_container) {
//Is the message there already?
var message_showing =
(track_list_container.find('.term_ref_tree_nothing_message').size() != 0);
//Number of real items showing.
var num_real_items_showing =
message_showing
? track_list_container.find('li').size() - 1
: track_list_container.find('li').size();
if ( num_real_items_showing == 0 ) {
//No items showing, so show the message.
if ( ! message_showing ) {
track_list_container.append(
'<li class="term_ref_tree_nothing_message">' + termReferenceTreeNothingSelectedText + '</li>'
);
else {
//There is an item on the list.
var current_item = $(current_items.get(0));
//Is the item we want to add different from what is there?
if ( current_item.data('control_id') != control_id ) {
//Remove exiting element from track list, and add the new one.
current_item.remove();
track_list_container.append(new_item);
}
}
else { // !(num_real_items_showing == 0)
//There are real items.
if ( message_showing ) {
track_list_container.find('.term_ref_tree_nothing_message').remove();
return;
}
//Using checkboxes, so there can be more than one selected item.
//Find the right place to put the new item, to match the order of the
//checkboxes.
var list_items = track_list_container.find('li');
var item_comparing_to;
//Flag to tell whether the item was inserted.
var inserted_flag = false;
list_items.each(function(index){
item_comparing_to = $(list_items[index]);
//If item is already on the track list, do nothing.
if ( control_id == item_comparing_to.data('control_id') ) {
inserted_flag = true;
return false; //Returning false stops the loop.
}
else if ( control_id < item_comparing_to.data('control_id') ) {
//Add it here.
item_comparing_to.before(new_item);
inserted_flag = true;
return false; //Returning false stops the loop.
}
});
//If not inserted yet, add new item at the end of the track list.
if ( ! inserted_flag ) {
track_list_container.append(new_item);
}
}
/**
* Show the 'nothing selected' message if it applies.
*
* @param track_list_container Where the message is to be shown.
*/
function showNothingSelectedMessage(track_list_container) {
//Is the message there already?
var message_showing =
(track_list_container.find('.term_ref_tree_nothing_message').size() != 0);
//Number of real items showing.
var num_real_items_showing =
message_showing
? track_list_container.find('li').size() - 1
: track_list_container.find('li').size();
if ( num_real_items_showing == 0 ) {
//No items showing, so show the message.
if ( ! message_showing ) {
track_list_container.append(
'<li class="term_ref_tree_nothing_message">' + termReferenceTreeNothingSelectedText + '</li>'
);
}
}
else { // !(num_real_items_showing == 0)
//There are real items.
if ( message_showing ) {
track_list_container.find('.term_ref_tree_nothing_message').remove();
}
}
}
/**
* Remove the 'nothing selected' message. Makes processing easier.
*
* @param track_list_container Where the message is shown.
*/
function removeNothingSelectedMessage(track_list_container) {
track_list_container.find('.term_ref_tree_nothing_message').remove();
}
// This helper function checks if the maximum number of choices is already selected.
// If so, it disables all the other options. If not, it enables them.
function checkMaxChoices(item, checkbox) {
var maxChoices = -1;
try {
maxChoices = parseInt(Drupal.settings.term_reference_tree.trees[item.attr('id')]['max_choices']);
}
catch (e){}
var count = item.find(':checked').length;
if(maxChoices > 0 && count >= maxChoices) {
item.find('input[type=checkbox]:not(:checked)').attr('disabled', 'disabled').parent().addClass('disabled');
} else {
item.find('input[type=checkbox]').removeAttr('disabled').parent().removeClass('disabled');
}
if(checkbox) {
if(item.hasClass('select-parents')) {
var track_list_container = item.find('.term-reference-tree-track-list');
var input_type =
( item.has('input[type=checkbox]').size() > 0 ) ? 'checkbox' : 'radio';
if(checkbox.attr('checked')) {
checkbox.parents('ul.term-reference-tree-level li').children('div.form-item').children('input[type=checkbox]').each(function() {
$(this).attr('checked', checkbox.attr('checked'));
if(track_list_container) {
label_element = $(this).next();
addItemToTrackList(
track_list_container, //Where to add new item.
label_element.html(), //Text of new item.
$(label_element).attr('for'), //Id of control new item is for.
input_type //checkbox or radio
);
}
});
}
}
}
}
/**
* Remove the 'nothing selected' message. Makes processing easier.
*
* @param track_list_container Where the message is shown.
*/
function removeNothingSelectedMessage(track_list_container) {
track_list_container.find('.term_ref_tree_nothing_message').remove();
}
// This helper function checks if the maximum number of choices is already selected.
// If so, it disables all the other options. If not, it enables them.
function checkMaxChoices(item, checkbox) {
var maxChoices = -1;
try {
maxChoices = parseInt(Drupal.settings.term_reference_tree.trees[item.attr('id')]['max_choices']);
}
catch (e){}
var count = item.find(':checked').length;
if(maxChoices > 0 && count >= maxChoices) {
item.find('input[type=checkbox]:not(:checked)').attr('disabled', 'disabled').parent().addClass('disabled');
} else {
item.find('input[type=checkbox]').removeAttr('disabled').parent().removeClass('disabled');
}
if(checkbox) {
if(item.hasClass('select-parents')) {
var track_list_container = item.find('.term-reference-tree-track-list');
var input_type =
( item.has('input[type=checkbox]').size() > 0 ) ? 'checkbox' : 'radio';
if(checkbox.attr('checked')) {
checkbox.parents('ul.term-reference-tree-level li').children('div.form-item').children('input[type=checkbox]').each(function() {
$(this).attr('checked', checkbox.attr('checked'));
if(track_list_container) {
label_element = $(this).next();
addItemToTrackList(
track_list_container, //Where to add new item.
label_element.html(), //Text of new item.
$(label_element).attr('for'), //Id of control new item is for.
input_type //checkbox or radio
);
}
});
}
}
}
}
})(jQuery);
})(jQuery);
@@ -9,33 +9,33 @@ module_load_include('inc', 'term_reference_tree', 'term_reference_tree.widget');
function term_reference_tree_element_info() {
$types = array(
'checkbox_tree' => array(
'#input' => true,
'#input' => TRUE,
'#process' => array('term_reference_tree_process_checkbox_tree'),
'#theme' => array('checkbox_tree'),
'#pre_render' => array('form_pre_render_conditional_form_element'),
),
'checkbox_tree_level' => array(
'#input' => false,
'#input' => FALSE,
'#theme' => array('checkbox_tree_level'),
'#pre_render' => array('form_pre_render_conditional_form_element'),
),
'checkbox_tree_item' => array(
'#input' => false,
'#input' => FALSE,
'#theme' => array('checkbox_tree_item'),
'#pre_render' => array('form_pre_render_conditional_form_element'),
),
'checkbox_tree_label' => array(
'#input' => false,
'#input' => FALSE,
'#theme' => array('checkbox_tree_label'),
'#pre_render' => array('form_pre_render_conditional_form_element'),
),
'checkbox_tree_track_list' => array(
'#input' => false,
'#input' => FALSE,
'#theme' => array('checkbox_tree_track_list'),
'#pre_render' => array('form_pre_render_conditional_form_element'),
),
);
return $types;
}
@@ -75,38 +75,22 @@ function term_reference_tree_theme() {
* The vocabulary ID to restrict the child search.
*
* @return
* A nested array of the term's child objects.
* A nested array of the term's child objects.
*/
function _term_reference_tree_get_term_hierarchy($tid, $vid, &$allowed, $filter, $label, $default = array()) {
$terms = _term_reference_tree_get_children($tid, $vid, $default);
$result = array();
if ($filter != '') {
foreach($allowed as $k => $v) {
foreach ($allowed as $k => $v) {
if (array_key_exists($k, $terms)) {
$term =& $terms[$k];
$children = _term_reference_tree_get_term_hierarchy($term->tid, $vid, $allowed, $filter, $label, $default);
if (is_array($children)) {
$term->children = $children;
$term->children_selected = _term_reference_tree_children_selected($term, $default);
}
else {
$term->children_selected = FALSE;
$term->children_selected = _term_reference_tree_children_selected($term, $default);
}
$term->TEST = $label;
array_push($result, $term);
}
}
}
else {
foreach($terms as &$term) {
if ($filter == '' || array_key_exists($term->tid, $allowed)) {
$children = _term_reference_tree_get_term_hierarchy($term->tid, $vid, $allowed, $filter, $label, $default);
if (is_array($children)) {
$term->children = $children;
$term->children_selected = _term_reference_tree_children_selected($term, $default);
}
else {
$term->children_selected = FALSE;
}
@@ -115,7 +99,23 @@ function _term_reference_tree_get_term_hierarchy($tid, $vid, &$allowed, $filter,
}
}
}
else {
foreach ($terms as &$term) {
if ($filter == '' || array_key_exists($term->tid, $allowed)) {
$children = _term_reference_tree_get_term_hierarchy($term->tid, $vid, $allowed, $filter, $label, $default);
if (is_array($children)) {
$term->children = $children;
$term->children_selected = _term_reference_tree_children_selected($term, $default);
}
else {
$term->children_selected = FALSE;
}
$term->TEST = $label;
array_push($result, $term);
}
}
}
return $result;
}
@@ -136,38 +136,41 @@ function _term_reference_tree_get_children($tid, $vid) {
// very bad on large vocabularies. Instead, we load the term as necessary
// in cases where it's needed (such as using tokens or when the locale
// module is enabled).
$select = db_select('taxonomy_term_data', 'd');
$select->join('taxonomy_term_hierarchy', 'h', 'd.tid = h.tid');
$result = $select->fields('d', array('tid', 'name'))
->condition('d.vid', $vid, '=')
->condition('h.parent', $tid, '=')
->orderBy('weight')
->orderBy('name')
->orderBy('tid')
->execute();
$query = db_select('taxonomy_term_data', 't');
$query->join('taxonomy_term_hierarchy', 'h', 't.tid = h.tid');
$query->join('taxonomy_vocabulary', 'v', 'v.vid = t.vid');
$query->fields('t', array('tid', 'name'));
$query->addField('v', 'machine_name', 'vocabulary_machine_name');
$query->condition('t.vid', $vid);
$query->condition('h.parent', $tid);
$query->addTag('term_access');
$query->addTag('translatable');
$query->orderBy('t.weight');
$query->orderBy('t.name');
$results = $query->execute();
$terms = array();
while($term = $result->fetchAssoc()) {
$terms[$term['tid']] = (object) $term;
while ($term = $results->fetchObject()) {
$terms[$term->tid] = $term;
}
return $terms;
}
function _term_reference_tree_children_selected($terms, $default) {
foreach($terms->children as $term) {
if(isset($default[$term->tid]) || $term->children_selected) {
return true;
foreach ($terms->children as $term) {
if (isset($default[$term->tid]) || $term->children_selected) {
return TRUE;
}
}
return false;
return FALSE;
}
function _term_reference_tree_get_parent($tid) {
$q = db_query_range("select h.parent from {taxonomy_term_hierarchy} h where h.tid = :tid", 0, 1, array(':tid' => $tid));
$q = db_query_range("SELECT h.parent FROM {taxonomy_term_hierarchy} h WHERE h.tid = :tid", 0, 1, array(':tid' => $tid));
$t = 0;
foreach($q as $term) {
foreach ($q as $term) {
$t = $term->parent;
}
@@ -181,7 +184,7 @@ function _term_reference_tree_get_parent($tid) {
function _term_reference_tree_flatten($element, &$form_state) {
$output = array();
$children = element_children($element);
foreach($children as $c) {
foreach ($children as $c) {
$child = $element[$c];
if (array_key_exists('#type', $child) && ($child['#type'] == 'radio' || $child['#type'] == 'checkbox')) {
$output[] = $child;
@@ -195,9 +198,9 @@ function _term_reference_tree_flatten($element, &$form_state) {
/**
* Return an array of options.
*
*
* This function converts a list of taxonomy terms to a key/value list of options.
*
*
* @param $terms
* An array of taxonomy term IDs.
* @param $allowed
@@ -205,7 +208,7 @@ function _term_reference_tree_flatten($element, &$form_state) {
* @param $filter
* A string defining the view to filter by (only used to detect whether view
* filtering is enabled
*
*
* @return
* A key/value array of taxonomy terms (name => id)
*/
@@ -213,7 +216,7 @@ function _term_reference_tree_get_options(&$terms, &$allowed, $filter) {
$options = array();
if (is_array($terms) && count($terms) > 0) {
foreach($terms as $term) {
foreach ($terms as $term) {
if (!$filter || (is_array($allowed) && $allowed[$term->tid])) {
$options[$term->tid] = entity_label('taxonomy_term', $term);
$options += _term_reference_tree_get_options($term->children, $allowed, $filter);
@@ -222,4 +225,3 @@ function _term_reference_tree_get_options(&$terms, &$allowed, $filter) {
}
return $options;
}
@@ -5,11 +5,11 @@
*/
function term_reference_tree_field_widget_info() {
return array(
'term_reference_tree' => array (
'label' => 'Term reference tree',
'term_reference_tree' => array(
'label' => t('Term reference tree'),
'field types' => array('taxonomy_term_reference'),
'behaviors' => array(
'multiple values' => FIELD_BEHAVIOR_CUSTOM,
'multiple values' => FIELD_BEHAVIOR_CUSTOM,
'default value' => FIELD_BEHAVIOR_DEFAULT,
),
'settings' => array(
@@ -27,51 +27,6 @@ function term_reference_tree_field_widget_info() {
);
}
/**
* Themes the term tree display (as opposed to the select widget).
*/
function theme_term_tree_list($variables) {
$element =& $variables['element'];
$data =& $element['#data'];
$tree = array();
# For each selected term:
foreach($data as $item) {
# Loop if the term ID is not zero:
$values = array();
$tid = $item['tid'];
$original_tid = $tid;
while($tid != 0) {
# Unshift the term onto an array
array_unshift($values, $tid);
# Repeat with parent term
$tid = _term_reference_tree_get_parent($tid);
}
$current =& $tree;
# For each term in the above array:
foreach($values as $tid) {
# current[children][term_id] = new array
if (!isset($current['children'][$tid])) {
$current['children'][$tid] = array('selected' => FALSE);
}
# If this is the last value in the array, tree[children][term_id][selected] = true
if ($tid == $original_tid) {
$current['children'][$tid]['selected'] = TRUE;
}
$current['children'][$tid]['tid'] = $tid;
$current =& $current['children'][$tid];
}
}
return _term_reference_tree_output_list_level($element, $tree);
}
/**
* Implements hook_field_widget_settings_form().
*/
@@ -79,7 +34,7 @@ function term_reference_tree_field_widget_settings_form($field, $instance) {
$widget = $instance['widget'];
$settings = $widget['settings'];
$form = array();
if ($widget['type'] == 'term_reference_tree') {
$form['start_minimized'] = array(
'#type' => 'checkbox',
@@ -88,7 +43,7 @@ function term_reference_tree_field_widget_settings_form($field, $instance) {
'#default_value' => $settings['start_minimized'],
'#return_value' => 1,
);
$form['leaves_only'] = array(
'#type' => 'checkbox',
'#title' => t('Leaves only'),
@@ -118,10 +73,10 @@ function term_reference_tree_field_widget_settings_form($field, $instance) {
if (module_exists('views')) {
$views = views_get_all_views();
$options = array('' => 'none');
foreach($views as $name => $view) {
foreach ($views as $name => $view) {
if ($view->base_table == 'taxonomy_term_data') {
foreach($view->display as $display) {
foreach ($view->display as $display) {
$options["$name:{$display->id}"] = "{$view->human_name}: {$display->display_title}";
}
}
@@ -146,7 +101,7 @@ function term_reference_tree_field_widget_settings_form($field, $instance) {
$form['token_display'] = array(
'#type' => 'textarea',
'#title' => 'Custom Term Label',
'#description' => t("Use tokens to change the term labels for the checkboxes and/or radio buttons. Leave this field blank to use the term name."),
'#description' => t("Use tokens to change the term labels for the checkboxes and/or radio buttons. Leave this field blank to use the term name."),
'#default_value' => $settings['token_display'],
);
@@ -160,18 +115,16 @@ function term_reference_tree_field_widget_settings_form($field, $instance) {
'#type' => 'hidden',
'#value' => $settings['token_display'],
);
}
}
$form['track_list'] = array(
'#type' => 'checkbox',
'#title' => t('Track list'),
'#description' => t(
'Track what the user has chosen in a list below the tree.
Useful when the tree is large, with many levels.'),
'#description' => t('Track what the user has chosen in a list below the tree. Useful when the tree is large, with many levels.'),
'#default_value' => $settings['track_list'],
'#return_value' => 1,
);
$form['max_depth'] = array(
'#type' => 'textfield',
'#title' => t('Maximum Depth'),
@@ -179,21 +132,68 @@ function term_reference_tree_field_widget_settings_form($field, $instance) {
'#default_value' => $settings['max_depth'],
'#size' => 2,
'#return_value' => 1,
);
);
$form['parent_term_id'] = array(
'#type' => 'textfield',
'#title' => t('Parent Term ID'),
'#description' => t("Only show items underneath the taxonomy term with this ID number. Leave this field blank to not limit terms by parent."),
'#description' => t("Only show items underneath the taxonomy term with this ID number. Leave this field blank to not limit terms by parent."),
'#default_value' => $settings['parent_term_id'],
'#size' => 8,
'#return_value' => 1,
);
);
}
return $form;
}
/**
* Themes the term tree display (as opposed to the select widget).
*/
function theme_term_tree_list($variables) {
$element = &$variables['element'];
$data = &$element['#data'];
$tree = array();
// For each selected term:
foreach ($data as $item) {
// Loop if the term ID is not zero:
$values = array();
$tid = $item['tid'];
$original_tid = $tid;
while ($tid != 0) {
// Unshift the term onto an array
array_unshift($values, $tid);
// Repeat with parent term
$tid = _term_reference_tree_get_parent($tid);
}
$current = &$tree;
// For each term in the above array:
foreach ($values as $tid) {
// current[children][term_id] = new array
if (!isset($current['children'][$tid])) {
$current['children'][$tid] = array('selected' => FALSE);
}
// If this is the last value in the array, tree[children][term_id][selected] = true
if ($tid == $original_tid) {
$current['children'][$tid]['selected'] = TRUE;
}
$current['children'][$tid]['tid'] = $tid;
$current = &$current['children'][$tid];
}
}
$output = "<div class='term-tree-list'>";
$output .= _term_reference_tree_output_list_level($element, $tree);
$output .= "</div>";
return $output;
}
/**
* Helper function to output a single level of the term reference tree
* display.
@@ -205,9 +205,11 @@ function _term_reference_tree_output_list_level(&$element, &$tree) {
$tokens_selected = $settings['token_display_selected'];
$tokens_unselected = ($settings['token_display_unselected'] != '') ? $settings['token_display_unselected'] : $tokens_selected;
foreach($tree['children'] as &$item) {
$term = taxonomy_term_load($item['tid']);
$uri = taxonomy_term_uri($term);
$taxonomy_term_info = entity_get_info('taxonomy_term');
foreach ($tree['children'] as &$item) {
$term = $taxonomy_term_info['load hook']($item['tid']);
$uri = $taxonomy_term_info['uri callback']($term);
$uri['options']['html'] = TRUE;
$class = $item['selected'] ? 'selected' : 'unselected';
$output .= "<li class='$class'>";
if ($tokens_selected != '' && module_exists('token')) {
@@ -215,7 +217,7 @@ function _term_reference_tree_output_list_level(&$element, &$tree) {
$output .= token_replace($replace, array('term' => $term), array('clear' => TRUE));
}
else {
$output .= l(entity_label('taxonomy_term', $term), $uri['path'], array('html' => true));
$output .= l(filter_xss(entity_label('taxonomy_term', $term)), $uri['path'], $uri['options']);
}
if (isset($item['children'])) {
$output .= _term_reference_tree_output_list_level($element, $item);
@@ -253,40 +255,41 @@ function _term_reference_tree_cascading_selection_validate($element, &$form_stat
/**
* Process the checkbox_tree widget.
*
*
* This function processes the checkbox_tree widget.
*
*
* @param $element
* The element to be drawn.$element['#field_name']
* @param $form_state
* The form state.
*
*
* @return
* The processed element.
*/
function term_reference_tree_process_checkbox_tree($element, $form_state) {
if (is_array($form_state)) {
if (!empty($element['#max_choices']) && $element['#max_choices'] != '-1')
drupal_add_js(array('term_reference_tree' => array('trees' => array($element['#id'] => array('max_choices'=>$element['#max_choices'])))), 'setting');
if (!empty($element['#max_choices']) && $element['#max_choices'] != '-1') {
drupal_add_js(array('term_reference_tree' => array('trees' => array($element['#id'] => array('max_choices' => $element['#max_choices'])))), 'setting');
}
$allowed = '';
if ($element['#filter_view'] != '') {
$allowed = _term_reference_tree_get_allowed_values($element['#filter_view']);
}
$value = !empty($element['#default_value']) ? $element['#default_value'] : array();
if (empty($element['#options'])) {
$element['#options_tree'] = _term_reference_tree_get_term_hierarchy($element['#parent_tid'], $element['#vocabulary'], $allowed, $element['#filter_view'], '', $value);
$element['#options_tree'] = _term_reference_tree_get_term_hierarchy($element['#parent_tid'], $element['#vocabulary']->vid, $allowed, $element['#filter_view'], '', $value);
$required = $element['#required'];
if ($element['#max_choices'] == 1 && !$required) {
array_unshift($element['#options_tree'], (object) array(
'tid' => '',
'name' => 'N/A',
'depth' => 0
)
);
'depth' => 0,
'vocabulary_machine_name' => $element['#vocabulary']->machine_name,
));
}
$element['#options'] = _term_reference_tree_get_options($element['#options_tree'], $allowed, $element['#filter_view']);
}
@@ -297,22 +300,23 @@ function term_reference_tree_process_checkbox_tree($element, $form_state) {
$element['#attributes']['class'][] = 'select-parents';
}
if ($max_choices != 1)
if ($max_choices != 1) {
$element['#tree'] = TRUE;
}
$tree = new stdClass;
$tree = new stdClass();
$tree->children = $terms;
$element[] = _term_reference_tree_build_level($element, $tree, $form_state, $value, $max_choices, array(), 1);
//Add a track list element?
// Add a track list element?
$track_list = !empty($element['#track_list']) && $element['#track_list'];
if ( $track_list ) {
if ($track_list) {
$element[] = array(
'#type' => 'checkbox_tree_track_list',
'#max_choices' => $max_choices,
);
}
}
}
return $element;
}
@@ -329,17 +333,17 @@ function term_reference_tree_process_checkbox_tree($element, $form_state) {
function theme_checkbox_tree($variables) {
$element = $variables['element'];
$element['#children'] = drupal_render_children($element);
$attributes = array();
if (isset($element['#id'])) {
$attributes['id'] = $element['#id'];
}
$attributes['class'][] = 'term-reference-tree';
if (form_get_error($element)) {
$attributes['class'][] = 'error';
}
if (!empty($element['#required'])) {
$attributes['class'][] = 'required';
}
@@ -361,9 +365,9 @@ function theme_checkbox_tree($variables) {
if (!empty($element['#attributes']['class'])) {
$attributes['class'] = array_merge($attributes['class'], $element['#attributes']['class']);
}
return
'<div' . drupal_attributes($attributes) . '>'
. (!empty($element['#children']) ? $element['#children'] : '')
return
'<div' . drupal_attributes($attributes) . '>'
. (!empty($element['#children']) ? $element['#children'] : '')
. '</div>';
}
@@ -376,7 +380,6 @@ function theme_checkbox_tree_level($variables) {
$element = $variables['element'];
$sm = '';
if (array_key_exists('#level_start_minimized', $element) && $element['#level_start_minimized']) {
$collapsed =
$sm = " style='display: none;'";
}
@@ -387,7 +390,7 @@ function theme_checkbox_tree_level($variables) {
$output = "<ul class='term-reference-tree-level '$sm>";
$children = element_children($element);
foreach($children as $child) {
foreach ($children as $child) {
$output .= "<li>";
$output .= drupal_render($element[$child]);
$output .= "</li>";
@@ -406,9 +409,9 @@ function theme_checkbox_tree_item($variables) {
$element = $variables['element'];
$children = element_children($element);
$output = "";
$sm = $element['#level_start_minimized'] ? ' term-reference-tree-collapsed' : '';
if (is_array($children) && count($children) > 1) {
$output .= "<div class='term-reference-tree-button$sm'></div>";
}
@@ -416,10 +419,10 @@ function theme_checkbox_tree_item($variables) {
$output .= "<div class='no-term-reference-tree-button'></div>";
}
foreach($children as $child) {
foreach ($children as $child) {
$output .= drupal_render($element[$child]);
}
return $output;
}
@@ -437,51 +440,49 @@ function theme_checkbox_tree_label($variables) {
* The display happens on the client-side.
* Use this function to theme the element's label,
* and the "nothing selected" message.
*
* @param $variables Variables available for theming.
*
* @param $variables
* Variables available for theming.
*/
function theme_checkbox_tree_track_list($variables) {
//Should the label be singular or plural? Depends on cardinality of term field.
// Should the label be singular or plural? Depends on cardinality of term field.
static $nothingselected;
if(!$nothingselected) {
if (!$nothingselected) {
$nothingselected = t('[Nothing selected]');
//Add the "Nothing selected" text. To style it, replace it with whatever you want.
//Could do this with a file instead.
// Add the "Nothing selected" text. To style it, replace it with whatever you want.
// Could do this with a file instead.
drupal_add_js(
'var termReferenceTreeNothingSelectedText = "' . $nothingselected . '";',
'inline'
);
}
$label = format_plural(
$variables['element']['#max_choices'],
$variables['element']['#max_choices'],
'Selected item (click the item to uncheck it)',
'Selected items (click an item to uncheck it)'
);
$output =
'<div class="term-reference-track-list-container">
<div class="term-reference-track-list-label">' . $label . '</div>
<ul class="term-reference-tree-track-list"><li class="term_ref_tree_nothing_message">'.$nothingselected.'</li></ul>
</div>';
$output = '<div class="term-reference-track-list-container">';
$output .= '<div class="term-reference-track-list-label">' . $label . '</div>';
$output .= '<ul class="term-reference-tree-track-list"><li class="term_ref_tree_nothing_message">' . $nothingselected . '</li></ul>';
$output .= '</div>';
return $output;
}
/**
* Implements hook_widget_field_form().
* Implements hook_field_widget_form().
*/
function term_reference_tree_field_widget_form(&$form, &$form_state, $field, $instance, $langcode, $items, $delta, $element) {
$settings = $instance['widget']['settings'];
$voc = taxonomy_vocabulary_machine_name_load($field['settings']['allowed_values'][0]['vocabulary']);
$vocabulary = taxonomy_vocabulary_machine_name_load($field['settings']['allowed_values'][0]['vocabulary']);
$path = drupal_get_path('module', 'term_reference_tree');
$value_key = key($field['columns']);
$type = $instance['widget']['type'];
$default_value = array();
foreach($items as $item) {
foreach ($items as $item) {
$key = $item[$value_key];
if ($key === 0) {
$default_value[$key] = '0';
@@ -494,15 +495,16 @@ function term_reference_tree_field_widget_form(&$form, &$form_state, $field, $in
$multiple = $field['cardinality'] > 1 || $field['cardinality'] == FIELD_CARDINALITY_UNLIMITED;
$properties = array();
if (!array_key_exists('#value', $element))
if (!array_key_exists('#value', $element)) {
$element['#value'] = array();
}
// A switch statement, in case we ever add more widgets to this module.
switch($instance['widget']['type']) {
switch ($instance['widget']['type']) {
case 'term_reference_tree':
$element['#attached']['js'] = array($path . '/term_reference_tree.js');
$element['#attached']['css'] = array($path . '/term_reference_tree.css');
$element['#type'] = 'checkbox_tree';
$element['#type'] = 'checkbox_tree';
$element['#default_value'] = $multiple ? $default_value : array(reset($default_value) => reset($default_value));
$element['#max_choices'] = $field['cardinality'];
$element['#max_depth'] = $settings['max_depth'];
@@ -512,12 +514,12 @@ function term_reference_tree_field_widget_form(&$form, &$form_state, $field, $in
$element['#select_parents'] = $settings['select_parents'];
$element['#cascading_selection'] = $settings['cascading_selection'];
$element['#track_list'] = $settings['track_list'];
$element['#parent_tid'] = $settings['parent_term_id'] || $field['settings']['allowed_values'][0]['parent'];
$element['#vocabulary'] = $voc->vid;
$element['#parent_tid'] = $settings['parent_term_id'] ? $settings['parent_term_id'] : $field['settings']['allowed_values'][0]['parent'];
$element['#vocabulary'] = $vocabulary;
$element['#token_display'] = module_exists('token') ? $settings['token_display'] : '';
break;
}
$element += array(
'#value_key' => $value_key,
'#element_validate' => array('_term_reference_tree_widget_validate'),
@@ -530,16 +532,16 @@ function term_reference_tree_field_widget_form(&$form, &$form_state, $field, $in
/**
* Validates the term reference tree widgets.
*
*
* This function sets the value of the tree widgets into a form that Drupal
* can understand, and also checks if the field is required and has been
* left empty.
*
*
* @param $element
* The element to be validated.
* @param $form_state
* The state of the form.
*
*
* @return
* The validated element.
*/
@@ -548,20 +550,20 @@ function _term_reference_tree_widget_validate(&$element, &$form_state) {
$value = array();
if ($element['#max_choices'] != 1) {
foreach($items as $child) {
if (array_key_exists('#value', $child) && $child['#value'] !== 0) {
foreach ($items as $child) {
if (!empty($child['#value'])) {
array_push($value, array($element['#value_key'] => $child['#value']));
// If the element is leaves only and select parents is on, then automatically
// add all the parents of each selected value.
if ($element['#select_parents'] && $element['#leaves_only']) {
foreach($child['#parent_values'] as $parent_tid) {
foreach ($child['#parent_values'] as $parent_tid) {
if (!in_array(array($element['#value_key'] => $parent_tid), $value)) {
array_push($value, array($element['#value_key'] => $parent_tid));
}
}
}
}
}
}
}
else {
@@ -569,12 +571,12 @@ function _term_reference_tree_widget_validate(&$element, &$form_state) {
// grab the value of the first one.
if (count($items) > 0) {
$child = reset($items);
if (array_key_exists('#value', $child) && $child['#value'] !== 0) {
if (!empty($child['#value'])) {
array_push($value, array($element['#value_key'] => $child['#value']));
}
}
}
}
if ($element['#required'] && empty($value)) {
// The title is already check_plained so it's appropriate to use !.
form_error($element, t('!name field is required.', array('!name' => $element['#title'])));
@@ -607,8 +609,8 @@ function _term_reference_tree_get_allowed_values($filter) {
$title = drupal_get_title();
$view->execute_display($displayname);
$title = drupal_set_title($title, PASS_THROUGH);
foreach($view->result as $item) {
$allowed[$item->tid] = true;
foreach ($view->result as $item) {
$allowed[$item->tid] = TRUE;
}
}
else {
@@ -649,7 +651,7 @@ function _term_reference_tree_get_allowed_values($filter) {
* A completed checkbox_tree_item element, which contains a checkbox and
* possibly a checkbox_tree_level element as well.
*/
function _term_reference_tree_build_item(&$element, &$term, &$form_state, &$value, $max_choices, $parent_tids, $parent, $depth) {
function _term_reference_tree_build_item($element, $term, $form_state, $value, $max_choices, $parent_tids, $parent, $depth) {
$start_minimized = FALSE;
if (array_key_exists('#start_minimized', $element)) {
$start_minimized = $element['#start_minimized'];
@@ -660,11 +662,12 @@ function _term_reference_tree_build_item(&$element, &$term, &$form_state, &$valu
$leaves_only = $element['#leaves_only'];
}
$t = null;
if(module_exists('locale')) {
$t = NULL;
if (module_exists('locale') && !empty($term->tid)) {
$t = taxonomy_term_load($term->tid);
$term_name = entity_label('taxonomy_term', $t);
} else {
}
else {
$term_name = $term->name;
}
$container = array(
@@ -691,7 +694,7 @@ function _term_reference_tree_build_item(&$element, &$term, &$form_state, &$valu
);
if ($element['#token_display'] != '' && module_exists('token')) {
if(!$t) {
if (!$t) {
$t = taxonomy_term_load($term->tid);
}
$e['#title'] = token_replace($element['#token_display'], array('term' => $t), array('clear' => TRUE));
@@ -710,16 +713,15 @@ function _term_reference_tree_build_item(&$element, &$term, &$form_state, &$valu
);
}
$container[$term->tid] = $e;
$container[$term->tid] = $e;
if (($depth + 1 <= $element['#max_depth'] || !$element['#max_depth']) && property_exists($term, 'children') && count($term->children) > 0) {
$parents = $parent_tids;
$parents[] = $term->tid;
$container[$term->tid . '-children'] = _term_reference_tree_build_level($element, $term, $form_state, $value, $max_choices, $parents, $depth+1);
$container[$term->tid . '-children'] = _term_reference_tree_build_level($element, $term, $form_state, $value, $max_choices, $parents, $depth + 1);
$container['#level_start_minimized'] = $container[$term->tid . '-children']['#level_start_minimized'];
}
return $container;
}
@@ -744,7 +746,7 @@ function _term_reference_tree_build_item(&$element, &$term, &$form_state, &$valu
* @return
* A completed checkbox_tree_level element.
*/
function _term_reference_tree_build_level(&$element, &$term, &$form_state, &$value, $max_choices, $parent_tids, $depth) {
function _term_reference_tree_build_level($element, $term, $form_state, $value, $max_choices, $parent_tids, $depth) {
$start_minimized = FALSE;
if (array_key_exists('#start_minimized', $element)) {
$start_minimized = $element['#start_minimized'];
@@ -754,7 +756,7 @@ function _term_reference_tree_build_level(&$element, &$term, &$form_state, &$val
if (array_key_exists('#leaves_only', $element)) {
$leaves_only = $element['#leaves_only'];
}
$container = array(
'#type' => 'checkbox_tree_level',
'#max_choices' => $max_choices,
@@ -764,10 +766,10 @@ function _term_reference_tree_build_level(&$element, &$term, &$form_state, &$val
);
$container['#level_start_minimized'] = $depth > 1 && $element['#start_minimized'] && !($term->children_selected);
foreach($term->children as $t) {
$container[$t->tid] = _term_reference_tree_build_item($element, $t, $form_state, $value, $max_choices, $parent_tids, $container, $depth);
foreach ($term->children as $child) {
$container[$child->tid] = _term_reference_tree_build_item($element, $child, $form_state, $value, $max_choices, $parent_tids, $container, $depth);
}
return $container;
}