You are here

function hierarchical_select_get_hierarchy in Hierarchical Select 5.2

Generate the hierarchy object.

Parameters

$module: The module that should be used for HS hooks.

$selection: The selection based on which a HS should be rendered.

$save_lineage: Whether the "save lineage" option is enabled or not.

$enforce_deepest: Whether the "enforce deepest" option is enabled or not.

$all_option: Prepends a new option, that allows you to select all items at once.

$level_labels: An array of labels, one per level. Optional.

$params: An array of parameters, which may be necessary for some implementations. Optional.

$required: Whether the form item is required or not. (#required Forms API property)

$dropbox: A dropbox object, or FALSE.

Return value

A hierarchy object.

2 calls to hierarchical_select_get_hierarchy()
hierarchical_select_json in ./hierarchical_select.module
Menu callback; JSON callback: generates and outputs the appropriate HTML.
hierarchical_select_process in ./hierarchical_select.module
Hierarchical select form element processing function.

File

./hierarchical_select.module, line 338
This module defines the "hierarchical_select" form element, which is a greatly enhanced way for letting the user select an option in a hierarchy.

Code

function hierarchical_select_get_hierarchy($module, $selection, $save_lineage, $enforce_deepest, $all_option, $level_labels = array(), $params = array(), $required, $dropbox = FALSE) {
  $hierarchy = new stdClass();

  //
  // Build the lineage.
  //
  // Validate and clean up the selection.
  $selection = _hierarchical_select_validate_selection($selection, $module, $params);

  // If save_linage is enabled, reconstruct the lineage. This is necessary
  // because e.g. the taxonomy module stores the terms by order of weight and
  // lexicography, rather than by hierarchy.
  if ($save_lineage && is_array($selection) && count($selection) >= 2) {

    // Ensure the item in the root level is the first item in the selection.
    $root_level = array_keys(module_invoke($module, 'hierarchical_select_root_level', $params));
    for ($i = 0; $i < count($selection); $i++) {
      if (in_array($selection[$i], $root_level)) {
        if ($i != 0) {

          // Don't swap if it's already the first item.
          list($selection[0], $selection[$i]) = array(
            $selection[$i],
            $selection[0],
          );
        }
        break;
      }
    }

    // Reconstruct all sublevels.
    for ($i = 0; $i < count($selection); $i++) {
      $children = array_keys(module_invoke($module, 'hierarchical_select_children', $selection[$i], $params));

      // Ensure the next item in the selection is a child of the current item.
      for ($j = $i + 1; $j < count($selection); $j++) {
        if (in_array($selection[$j], $children)) {
          list($selection[$j], $selection[$i + 1]) = array(
            $selection[$i + 1],
            $selection[$j],
          );
        }
      }
    }
  }

  // When nothing is currently selected, the dropbox is enabled and at least
  // one selection has been added to the dropbox, then set the root level to
  // "<none>". Otherwise, default to the root level label.
  if ($selection == -1) {
    $hierarchy->lineage[0] = $dropbox && count($dropbox->lineages) > 0 ? 'none' : 'label_0';
  }
  else {

    // If save_lineage option is enabled, then the selection *is* a lineage.
    // If it's disabled, we have to generate one ourselves based on the
    // (deepest) selected item.
    if ($save_lineage) {

      // When the form item is optional, the "<none>" option can be selected,
      // thus only the first level will be displayed. As a result, we won't
      // receive an array as the selection, but only a single item. We convert
      // this into an array.
      $hierarchy->lineage = is_array($selection) ? $selection : array(
        0 => $selection,
      );
    }
    else {
      $selection = is_array($selection) ? $selection[0] : $selection;
      if (module_invoke($module, 'hierarchical_select_valid_item', $selection, $params)) {
        $hierarchy->lineage = module_invoke($module, 'hierarchical_select_lineage', $selection, $params);
      }
      else {

        // If the selected item is invalid, then start with an empty lineage.
        $hierarchy->lineage = array();
      }
    }
  }

  // If enforce_deepest is enabled, ensure that the lineage goes as deep as
  // possible: append values of items that will be selected by default.
  if ($enforce_deepest && !in_array($hierarchy->lineage[0], array(
    'none',
    'label_0',
  ))) {
    $hierarchy->lineage = _hierarchial_select_enforce_deepest_selection($hierarchy->lineage, $hierarchy->levels[0], $module, $params);
  }

  //
  // Build the levels.
  //
  // Start building the levels, initialize with the root level.
  $hierarchy->levels[0] = module_invoke($module, 'hierarchical_select_root_level', $params);

  // Prepend an "all" option to the root level when a dropbox is in use.
  if ($dropbox && $all_option) {
    $hierarchy->levels[0] = array(
      'all' => '<' . t('all') . '>',
    ) + $hierarchy->levels[0];
  }

  // Prepend a "<none>" option to the root level when:
  // - the form item is optional.
  // - enforce_deepest is enabled (use case: when level labels are disabled,
  //   this will be the initial value when the form item is required, so that
  //   the user /can/ select nothing, but will get a validation error)
  // - a dropbox is in use and at least one item has been selected.
  if (!$required || $enforce_deepest || $dropbox && count($dropbox->lineages) > 0) {
    $hierarchy->levels[0] = array(
      'none' => '<' . t('none') . '>',
    ) + $hierarchy->levels[0];
  }

  // Calculate the lineage's depth (starting from 0).
  $max_depth = count($hierarchy->lineage) - 1;

  // Build all sublevels, based on the lineage.
  for ($depth = 1; $depth <= $max_depth; $depth++) {
    $hierarchy->levels[$depth] = module_invoke($module, 'hierarchical_select_children', $hierarchy->lineage[$depth - 1], $params);
  }

  // If enforce_deepest is enabled and the root label is set, prepend it.
  if ($enforce_deepest && isset($level_labels[0]) && strlen($level_labels[0]) > 0) {
    $hierarchy->levels[0] = array(
      'label_0' => $level_labels[0],
    ) + $hierarchy->levels[0];
  }
  else {
    if (!$enforce_deepest) {

      // … prepend labels to every level …
      for ($depth = 0; $depth <= $max_depth; $depth++) {
        $hierarchy->levels[$depth] = array(
          'label_' . $depth => $level_labels[$depth],
        ) + $hierarchy->levels[$depth];
      }

      // … and have to add one more level if appropriate.
      $parent = $hierarchy->lineage[$max_depth];
      if (module_invoke($module, 'hierarchical_select_valid_item', $parent, $params)) {
        $children = module_invoke($module, 'hierarchical_select_children', $parent, $params);
        if (count($children)) {

          // We're good, let's add one level!
          $max_depth++;
          $first_child = reset(array_keys($children));
          $hierarchy->lineage[$max_depth] = 'label_' . $max_depth;
          $hierarchy->levels[$max_depth] = array(
            'label_' . $max_depth => $level_labels[$max_depth],
          ) + $children;
        }
      }
    }
  }
  return $hierarchy;
}