| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498 | 
							- <?php
 
- use \Drupal\Core\Render\Element;
 
- /**
 
-  * Implements hook_theme().
 
-  */
 
- function term_reference_tree_theme() {
 
-   return [
 
-     'checkbox_tree' => [
 
-       'render element' => 'element',
 
-       'function' => 'theme_checkbox_tree',
 
-     ],
 
-     'checkbox_tree_level' => [
 
-       'render element' => 'element',
 
-       'function' => 'theme_checkbox_tree_level',
 
-     ],
 
-     'checkbox_tree_item' => [
 
-       'render element' => 'element',
 
-       'function' => 'theme_checkbox_tree_item',
 
-     ],
 
-     'checkbox_tree_label' => [
 
-       'render element' => 'element',
 
-       'function' => 'theme_checkbox_tree_label',
 
-     ],
 
-     'term_tree_list' => [
 
-       'render element' => 'element',
 
-       'function' => 'theme_term_tree_list',
 
-     ],
 
-   ];
 
- }
 
- /**
 
-  * Returns HTML for a checkbox_tree form element.
 
-  */
 
- function theme_checkbox_tree($variables) {
 
-   $element = $variables['element'];
 
-   $element['#children'] = drupal_render_children($element);
 
-   $attributes = isset($element['#attributes']) ? $element['#attributes'] : [];
 
-   if (isset($element['#id'])) {
 
-     $attributes['id'] = $element['#id'];
 
-   }
 
-   $attributes['class'][] = 'term-reference-tree';
 
-   if (!empty($element['#required'])) {
 
-     $attributes['class'][] = 'required';
 
-   }
 
-   if (array_key_exists('#start_minimized', $element) && $element['#start_minimized']) {
 
-     $attributes['class'][] = 'term-reference-tree-collapsed';
 
-   }
 
-   if (array_key_exists('#track_list', $element) && $element['#track_list']) {
 
-     $attributes['class'][] = 'term-reference-tree-track-list-shown';
 
-   }
 
-   if (!empty($variables['element']['#select_parents'])) {
 
-     $attributes['class'][] = 'term-reference-tree-select-parents';
 
-   }
 
-   if ($variables['element']['#cascading_selection'] != \Drupal\term_reference_tree\Plugin\Field\FieldWidget\TermReferenceTree::CASCADING_SELECTION_NONE) {
 
-     $attributes['class'][] = 'term-reference-tree-cascading-selection';
 
-   }
 
-   if ($variables['element']['#cascading_selection'] == \Drupal\term_reference_tree\Plugin\Field\FieldWidget\TermReferenceTree::CASCADING_SELECTION_SELECT) {
 
-     $attributes['class'][] = 'term-reference-tree-cascading-selection-mode-select';
 
-   }
 
-   else {
 
-     if ($variables['element']['#cascading_selection'] == \Drupal\term_reference_tree\Plugin\Field\FieldWidget\TermReferenceTree::CASCADING_SELECTION_DESELECT) {
 
-       $attributes['class'][] = 'term-reference-tree-cascading-selection-mode-deselect';
 
-     }
 
-   }
 
-   if (!empty($element['#attributes']['class'])) {
 
-     $attributes['class'] = array_merge($attributes['class'], $element['#attributes']['class']);
 
-   }
 
-   return
 
-     '<div' . new \Drupal\Core\Template\Attribute($attributes) . '>'
 
-     . (!empty($element['#children']) ? $element['#children'] : '')
 
-     . '</div>';
 
- }
 
- /**
 
-  * This function prints a list item with a checkbox and an unordered list
 
-  * of all the elements inside it.
 
-  */
 
- function theme_checkbox_tree_level($variables) {
 
-   $element = $variables['element'];
 
-   $sm = '';
 
-   if (array_key_exists('#level_start_minimized', $element) && $element['#level_start_minimized']) {
 
-     $sm = ' style="display: none;"';
 
-   }
 
-   $output = '<ul class="term-reference-tree-level "' . $sm . '>';
 
-   $children = Element::children($element);
 
-   foreach ($children as $child) {
 
-     $output .= '<li>';
 
-     $output .= \Drupal::service('renderer')->render($element[$child]);
 
-     $output .= '</li>';
 
-   }
 
-   $output .= '</ul>';
 
-   return $output;
 
- }
 
- /**
 
-  * This function prints a single item in the tree, followed by that item's
 
-  * children (which may be another checkbox_tree_level).
 
-  */
 
- 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>';
 
-   }
 
-   elseif (!$element['#leaves_only']) {
 
-     $output .= '<div class="no-term-reference-tree-button"></div>';
 
-   }
 
-   foreach ($children as $child) {
 
-     $output .= drupal_render($element[$child]);
 
-   }
 
-   return $output;
 
- }
 
- /**
 
-  * This function prints a label that cannot be selected.
 
-  */
 
- function theme_checkbox_tree_label($variables) {
 
-   $element = $variables['element'];
 
-   $output = '<div class="parent-term">' . $element['#value'] . '</div>';
 
-   return $output;
 
- }
 
- /**
 
-  * This function returns a taxonomy term hierarchy in a nested array.
 
-  *
 
-  * @param $tid
 
-  *   The ID of the root term.
 
-  * @param $vid
 
-  *   The vocabulary ID to restrict the child search.
 
-  *
 
-  * @return
 
-  *   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);
 
-   $result = [];
 
-   if ($filter != '') {
 
-     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->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;
 
-         }
 
-         $term->TEST = $label;
 
-         array_push($result, $term);
 
-       }
 
-     }
 
-   }
 
-   return $result;
 
- }
 
- /**
 
-  * This function is like taxonomy_get_children, except it doesn't load the
 
-  * entire term.
 
-  *
 
-  * @param int $tid
 
-  *   The ID of the term whose children you want to get.
 
-  * @param int $vid
 
-  *   The vocabulary ID.
 
-  *
 
-  * @return array
 
-  *   Taxonomy terms, each in the form ['tid' => $tid, 'name' => $name].
 
-  */
 
- function _term_reference_tree_get_children($tid, $vid) {
 
-   // DO NOT LOAD TAXONOMY TERMS HERE.
 
-   // Taxonomy terms take a lot of time and memory to load, and this can be
 
-   // 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).
 
-   $table = 'taxonomy_term_field_data';
 
-   $alias = 't';
 
-   $query = \Drupal::database()
 
-     ->select($table, $alias);
 
-   $query->join('taxonomy_term__parent', 'p', 't.tid = p.entity_id');
 
-   $query->fields('t', ['tid', 'name']);
 
-   $query->addField('t', 'vid', 'vocabulary_machine_name');
 
-   $query
 
-     ->condition('t.vid', $vid)
 
-     ->condition('p.parent_target_id', $tid)
 
-     ->addTag('term_access')
 
-     ->addTag('translatable')
 
-     ->orderBy('t.weight')
 
-     ->orderBy('t.name');
 
-   $result = $query->execute();
 
-   $terms = [];
 
-   while ($term = $result->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;
 
-     }
 
-   }
 
-   return FALSE;
 
- }
 
- /**
 
-  * Recursively go through the option tree and return a flat array of options.
 
-  */
 
- function _term_reference_tree_flatten($element, &$form_state) {
 
-   $output = array();
 
-   $children = \Drupal\Core\Render\Element::children($element);
 
-   foreach ($children as $c) {
 
-     $child = $element[$c];
 
-     if (array_key_exists('#type', $child) && ($child['#type'] == 'radio' || $child['#type'] == 'checkbox')) {
 
-       $output[] = $child;
 
-     }
 
-     else {
 
-       $output = array_merge($output, _term_reference_tree_flatten($child, $form_state));
 
-     }
 
-   }
 
-   return $output;
 
- }
 
- /**
 
-  * Return an array of options.
 
-  *
 
-  * This function converts a list of taxonomy terms to a key/value list of
 
-  * options.
 
-  */
 
- function _term_reference_tree_get_options(&$terms, &$allowed, $filter) {
 
-   $options = array();
 
-   if (is_array($terms) && count($terms) > 0) {
 
-     foreach ($terms as $term) {
 
-       if (!$filter || (is_array($allowed) && $allowed[$term->tid])) {
 
-         $options[$term->tid] = $term->name;
 
-         $options += _term_reference_tree_get_options($term->children, $allowed, $filter);
 
-       }
 
-     }
 
-   }
 
-   return $options;
 
- }
 
- /**
 
-  * Builds a level in the term reference tree widget.
 
-  *
 
-  * This function returns an element that has a number of checkbox_tree_item
 
-  * elements as children.  It is meant to be called recursively when the widget
 
-  * is built.
 
-  */
 
- function _term_reference_tree_build_level($element, $term, $form_state, $value, $max_choices, $parent_tids, $depth) {
 
-   $start_minimized = TRUE;
 
-   $leaves_only = FALSE;
 
-   $container = array(
 
-     '#type' => 'checkbox_tree_level',
 
-     '#max_choices' => $max_choices,
 
-     '#leaves_only' => $leaves_only,
 
-     '#start_minimized' => $start_minimized,
 
-     '#depth' => $depth,
 
-   );
 
-   $container['#level_start_minimized'] = $depth > 1 && $element['#start_minimized'] && !($term->children_selected);
 
-   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;
 
- }
 
- /**
 
-  * Builds a single item in the term reference tree widget.
 
-  *
 
-  * This function returns an element with a checkbox for a single taxonomy term.
 
-  * If that term has children, it appends checkbox_tree_level element that
 
-  * contains the children.  It is meant to be called recursively when the widget
 
-  * is built.
 
-  */
 
- function _term_reference_tree_build_item($element, $term, $form_state, $value, $max_choices, $parent_tids, $parent, $depth) {
 
-   $leaves_only = FALSE;
 
-   $langcode = \Drupal::languageManager()->getCurrentLanguage()->getId();
 
-   $t = NULL;
 
-   if (\Drupal::moduleHandler()->moduleExists('locale') && !empty($term->tid)) {
 
-     $t = \Drupal::entityManager()
 
-       ->getStorage('taxonomy_term')
 
-       ->load($term->tid);
 
-     if ($t && $t->hasTranslation($langcode)) {
 
-       $term_name = $t->getTranslation($langcode)->label();
 
-     }
 
-   }
 
-   if (empty($term_name)) {
 
-     $term_name = $term->name;
 
-   }
 
-   $container = array(
 
-     '#type' => 'checkbox_tree_item',
 
-     '#max_choices' => $max_choices,
 
-     '#leaves_only' => $leaves_only,
 
-     '#term_name' => $term_name,
 
-     '#level_start_minimized' => FALSE,
 
-     '#select_parents' => $element['#select_parents'],
 
-     '#depth' => $depth,
 
-   );
 
-   if (!$element['#leaves_only'] || count($term->children) == 0) {
 
-     $e = array(
 
-       '#type' => ($max_choices == 1) ? 'radio' : 'checkbox',
 
-       '#title' => $term_name,
 
-       '#on_value' => $term->tid,
 
-       '#off_value' => 0,
 
-       '#return_value' => $term->tid,
 
-       '#parent_values' => $parent_tids,
 
-       '#default_value' => isset($value[$term->tid]) ? $term->tid : NULL,
 
-       '#attributes' => isset($element['#attributes']) ? $element['#attributes'] : NULL,
 
-       '#ajax' => isset($element['#ajax']) ? $element['#ajax'] : NULL,
 
-     );
 
-     if ($e['#type'] == 'radio') {
 
-       $parents_for_id = array_merge($element['#parents'], array($term->tid));
 
-       $e['#id'] = \Drupal\Component\Utility\Html::getId('edit-' . implode('-', $parents_for_id));
 
-       $e['#parents'] = $element['#parents'];
 
-     }
 
-   }
 
-   else {
 
-     $e = array(
 
-       '#type' => 'checkbox_tree_label',
 
-       '#value' => $term_name,
 
-     );
 
-   }
 
-   $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['#level_start_minimized'] = $container[$term->tid . '-children']['#level_start_minimized'];
 
-   }
 
-   return $container;
 
- }
 
- /**
 
-  * Themes the term tree display (as opposed to the select widget).
 
-  */
 
- function theme_term_tree_list($variables) {
 
-   $element = &$variables['element'];
 
-   $data = &$element['#data'];
 
-   $tree = [];
 
-   // For each selected term.
 
-   foreach ($data as $item) {
 
-     // Loop if the term ID is not zero.
 
-     $values = [];
 
-     $tid = $item['target_id'];
 
-     $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] = ['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 get the parent of tid.
 
-  *
 
-  * @param int $tid
 
-  *   The term id.
 
-  *
 
-  * @return int
 
-  *   Parent term id or 0.
 
-  */
 
- function _term_reference_tree_get_parent($tid) {
 
-   $query = "SELECT p.parent_target_id FROM {taxonomy_term__parent} p WHERE p.entity_id = :tid";
 
-   $from = 0;
 
-   $count = 1;
 
-   $args = [':tid' => $tid];
 
-   $database = \Drupal::database();
 
-   $result = $database->queryRange($query, $from, $count, $args);
 
-   $parent_tid = 0;
 
-   foreach ($result as $term) {
 
-     $parent_tid = $term->parent_target_id;
 
-   }
 
-   return $parent_tid;
 
- }
 
- /**
 
-  * Helper function to output a single level of the term reference tree display.
 
-  */
 
- function _term_reference_tree_output_list_level(&$element, &$tree) {
 
-   $output = '';
 
-   $langcode = \Drupal::languageManager()->getCurrentLanguage()->getId();
 
-   if (isset($tree['children']) && is_array($tree['children']) && count($tree['children']) > 0) {
 
-     $output = '<ul class="term">';
 
-     foreach ($tree['children'] as &$item) {
 
-       if (isset($item['tid'])) {
 
-         $term = \Drupal\taxonomy\Entity\Term::load($item['tid']);
 
-         $url = $term->toUrl();
 
-         $uri['options']['html'] = TRUE;
 
-         $class = $item['selected'] ? 'selected' : 'unselected';
 
-         $output .= '<li class="' . $class . '">';
 
-         $t = NULL;
 
-         $term_name = '';
 
-         if (\Drupal::moduleHandler()
 
-             ->moduleExists('locale') && !empty($term->tid)) {
 
-           $t = $term;
 
-           if ($t && $t->hasTranslation($langcode)) {
 
-             $term_name = $t->getTranslation($langcode)->label();
 
-           }
 
-         }
 
-         if (empty($term_name)) {
 
-           $term_name = $term->label();
 
-         }
 
-         $output .= \Drupal::service('link_generator')
 
-           ->generate($term_name, $url);
 
-         if (isset($item['children'])) {
 
-           $output .= _term_reference_tree_output_list_level($element, $item);
 
-         }
 
-         $output .= '</li>';
 
-       }
 
-     }
 
-     $output .= '</ul>';
 
-   }
 
-   return $output;
 
- }
 
 
  |