|
@@ -0,0 +1,226 @@
|
|
|
+<?php
|
|
|
+
|
|
|
+module_load_include('inc', 'term_reference_tree', 'term_reference_tree.field');
|
|
|
+module_load_include('inc', 'term_reference_tree', 'term_reference_tree.widget');
|
|
|
+
|
|
|
+/**
|
|
|
+ * Implements hook_element_info().
|
|
|
+ */
|
|
|
+function term_reference_tree_element_info() {
|
|
|
+ $types = array(
|
|
|
+ 'checkbox_tree' => array(
|
|
|
+ '#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,
|
|
|
+ '#theme' => array('checkbox_tree_level'),
|
|
|
+ '#pre_render' => array('form_pre_render_conditional_form_element'),
|
|
|
+ ),
|
|
|
+ 'checkbox_tree_item' => array(
|
|
|
+ '#input' => false,
|
|
|
+ '#theme' => array('checkbox_tree_item'),
|
|
|
+ '#pre_render' => array('form_pre_render_conditional_form_element'),
|
|
|
+ ),
|
|
|
+ 'checkbox_tree_label' => array(
|
|
|
+ '#input' => false,
|
|
|
+ '#theme' => array('checkbox_tree_label'),
|
|
|
+ '#pre_render' => array('form_pre_render_conditional_form_element'),
|
|
|
+ ),
|
|
|
+ 'checkbox_tree_track_list' => array(
|
|
|
+ '#input' => false,
|
|
|
+ '#theme' => array('checkbox_tree_track_list'),
|
|
|
+ '#pre_render' => array('form_pre_render_conditional_form_element'),
|
|
|
+ )
|
|
|
+ );
|
|
|
+
|
|
|
+ return $types;
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * Implements hook_theme().
|
|
|
+ */
|
|
|
+function term_reference_tree_theme() {
|
|
|
+ return array(
|
|
|
+ 'checkbox_tree' => array(
|
|
|
+ 'render element' => 'element',
|
|
|
+ ),
|
|
|
+ 'checkbox_tree_level' => array(
|
|
|
+ 'render element' => 'element',
|
|
|
+ ),
|
|
|
+ 'checkbox_tree_item' => array(
|
|
|
+ 'render element' => 'element',
|
|
|
+ ),
|
|
|
+ 'checkbox_tree_label' => array(
|
|
|
+ 'render element' => 'element',
|
|
|
+ ),
|
|
|
+ 'checkbox_tree_track_list' => array(
|
|
|
+ 'render element' => 'element',
|
|
|
+ ),
|
|
|
+ 'term_tree_list' => array(
|
|
|
+ 'render element' => 'element',
|
|
|
+ ),
|
|
|
+ );
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+/**
|
|
|
+ * 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, $default);
|
|
|
+
|
|
|
+ $result = array();
|
|
|
+
|
|
|
+ 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 $tid
|
|
|
+ * The ID of the term whose children you want to get.
|
|
|
+ * @param $vid
|
|
|
+ * The vocabulary ID.
|
|
|
+ *
|
|
|
+ * @return
|
|
|
+ * An array of taxonomy terms, each in the form array('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).
|
|
|
+ $select = db_select('taxonomy_term_data', 'd');
|
|
|
+ $select->join('taxonomy_term_hierarchy', 'h', 'd.tid = h.tid');
|
|
|
+ $result = $select->fields('d', array('tid', 'vid', 'name'))
|
|
|
+ ->condition('d.vid', $vid, '=')
|
|
|
+ ->condition('h.parent', $tid, '=')
|
|
|
+ ->orderBy('weight')
|
|
|
+ ->orderBy('name')
|
|
|
+ ->orderBy('tid')
|
|
|
+ ->execute();
|
|
|
+
|
|
|
+ $terms = array();
|
|
|
+ while($term = $result->fetchAssoc()) {
|
|
|
+ $terms[$term['tid']] = (object) $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;
|
|
|
+}
|
|
|
+
|
|
|
+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));
|
|
|
+
|
|
|
+ $t = 0;
|
|
|
+ foreach($q as $term) {
|
|
|
+ $t = $term->parent;
|
|
|
+ }
|
|
|
+
|
|
|
+ return $t;
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * Recursively go through the option tree and return a flat array of
|
|
|
+ * options
|
|
|
+ */
|
|
|
+function _term_reference_tree_flatten($element, &$form_state) {
|
|
|
+ $output = array();
|
|
|
+ $children = element_children($element);
|
|
|
+ foreach($children as $c) {
|
|
|
+ $child = $element[$c];
|
|
|
+ // dsm($child, '$child');
|
|
|
+ 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.
|
|
|
+ *
|
|
|
+ * @param $terms
|
|
|
+ * An array of taxonomy term IDs.
|
|
|
+ * @param $allowed
|
|
|
+ * An array containing the terms allowed by the filter view
|
|
|
+ * @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)
|
|
|
+ */
|
|
|
+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] = entity_label('taxonomy_term', $term);
|
|
|
+ $options += _term_reference_tree_get_options($term->children, $allowed, $filter);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return $options;
|
|
|
+}
|
|
|
+
|