CheckboxTree.php 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  1. <?php
  2. namespace Drupal\term_reference_tree\Element;
  3. use Drupal\Core\Form\FormStateInterface;
  4. use Drupal\Core\Render\Element\CompositeFormElementTrait;
  5. use Drupal\Core\Render\Element\FormElement;
  6. /**
  7. * Provides a form element for term reference tree.
  8. *
  9. * @FormElement("checkbox_tree")
  10. */
  11. class CheckboxTree extends FormElement {
  12. use CompositeFormElementTrait;
  13. /**
  14. * {@inheritdoc}
  15. */
  16. public function getInfo() {
  17. $class = get_class($this);
  18. return [
  19. '#input' => TRUE,
  20. '#tree' => TRUE,
  21. '#process' => [
  22. [$class, 'processCheckboxTree'],
  23. ],
  24. '#pre_render' => [
  25. [$class, 'preRenderCompositeFormElement'],
  26. ],
  27. '#default_value' => [],
  28. '#attached' => [
  29. 'library' => [
  30. 'term_reference_tree/term_reference_tree_js',
  31. 'term_reference_tree/term_reference_tree_css',
  32. ],
  33. ],
  34. '#theme' => 'checkbox_tree',
  35. ];
  36. }
  37. /**
  38. * Processes a checkboxes form element.
  39. */
  40. public static function processCheckboxTree(&$element, FormStateInterface $form_state, &$complete_form) {
  41. $value = is_array($element['#value']) ? $element['#value'] : [];
  42. $allowed = [];
  43. $filter = FALSE;
  44. if (!empty($element['#max_choices']) && $element['#max_choices'] != '-1') {
  45. $element['#attached']['drupalSettings'] = [
  46. 'term_reference_tree' => [
  47. 'trees' => [
  48. $element['#id'] => [
  49. 'max_choices' => $element['#max_choices'],
  50. ],
  51. ],
  52. ],
  53. ];
  54. }
  55. if (!empty($element['#allowed'])) {
  56. $allowed = $element['#allowed'];
  57. $filter = TRUE;
  58. }
  59. if (empty($element['#options'])) {
  60. $options_tree = [];
  61. foreach ($element['#vocabularies'] as $vocabulary) {
  62. $options = _term_reference_tree_get_term_hierarchy(0, $vocabulary->id(), $allowed, $filter, '', $value);
  63. $options_tree = array_merge($options_tree, $options);
  64. }
  65. $element['#options_tree'] = $options_tree;
  66. $element['#options'] = _term_reference_tree_get_options($element['#options_tree'], $allowed, $filter);
  67. }
  68. $terms = !empty($element['#options_tree']) ? $element['#options_tree'] : [];
  69. $tree = new \stdClass();
  70. $tree->children = $terms;
  71. unset($element['#needs_validation']);
  72. $element['checkbox_tree'] = _term_reference_tree_build_level($element, $tree, $form_state, $value, $element['#max_choices'], [], 1);
  73. // track list
  74. if ($element['#track_list']) {
  75. if($form_state->getTriggeringElement()){
  76. // we are on ajax
  77. // $value is not updated on ajax callback
  78. // we need an other way to get wich options are checked
  79. // and give an accurate track list
  80. $parent = $element['#parents'][0]; // get the element's parent field
  81. $input = $form_state->getUserInput(); // get all inputs from form state
  82. $checkbox_tree_input = $input[$parent]['checkbox_tree']; // get the chekbox_tree input
  83. $selected = _term_reference_tree_get_flatten_selected_values($checkbox_tree_input); // get selected flattenized
  84. $track_list_input = $input[$parent]['track_list']; // get the current track_list input with correct order
  85. $old_list = array_keys($track_list_input); // flattenize
  86. // remove all chebox_tree input unselected from the list
  87. $list = [];
  88. foreach ($old_list as $id) {
  89. if(in_array($id, $selected)){
  90. $list[] = $id;
  91. }
  92. }
  93. // append newly selected
  94. $diff = array_diff($selected, $list);
  95. foreach ($diff as $id) {
  96. $list[] = $id;
  97. }
  98. }else{
  99. // if not ajax just get the default value
  100. $list = $value;
  101. }
  102. // build the track_list form element
  103. $element['track_list'] = _term_reference_tree_build_track_list_order($list, $element['#options']);
  104. }
  105. return $element;
  106. }
  107. /**
  108. * {@inheritdoc}
  109. */
  110. public static function valueCallback(&$element, $input, FormStateInterface $form_state) {
  111. $value = [];
  112. $element += ['#default_value' => []];
  113. foreach ($element['#default_value'] as $key) {
  114. if (isset($key['target_id'])) {
  115. $value[$key['target_id']] = $key['target_id'];
  116. }
  117. }
  118. return $value;
  119. }
  120. }