View source
<?php
define('HS_DEVELOPER_MODE', 0);
function hierarchical_select_help($path, $arg) {
switch ($path) {
case 'admin/help#hierarchical_select':
return t("Hierarchical Select has the ability to save the entire lineage\n of a selection or only the 'deepest' selection. You can configure it to\n force the user to make a selection as deep as possible in the tree, or\n allow the user to select an item anywhere in the tree. Levels can be\n labeled, you can configure limit the number of items that can be selected,\n configure a title for the dropbox, choose a site-wide animation delay,\n and so on. You can even create new items and levels through Hierarchical\n Select!");
}
}
function hierarchical_select_menu() {
$items['hierarchical_select_ajax'] = array(
'page callback' => 'hierarchical_select_ajax',
'delivery callback' => 'ajax_deliver',
'access arguments' => array(
'access content',
),
'theme callback' => 'ajax_base_page_theme',
'type' => MENU_CALLBACK,
);
$items['admin/config/content/hierarchical_select'] = array(
'title' => 'Hierarchical Select',
'description' => 'Configure site-wide settings for the Hierarchical Select form element.',
'access arguments' => array(
'administer site configuration',
),
'page callback' => 'drupal_get_form',
'page arguments' => array(
'hierarchical_select_admin_settings',
),
'type' => MENU_NORMAL_ITEM,
'file' => 'hierarchical_select.admin.inc',
);
$items['admin/config/content/hierarchical_select/settings'] = array(
'title' => 'Site-wide settings',
'access arguments' => array(
'administer site configuration',
),
'weight' => -10,
'type' => MENU_DEFAULT_LOCAL_TASK,
'file' => 'hierarchical_select.admin.inc',
);
$items['admin/config/content/hierarchical_select/configs'] = array(
'title' => 'Configurations',
'description' => 'All available Hierarchical Select configurations.',
'access arguments' => array(
'administer site configuration',
),
'page callback' => 'hierarchical_select_admin_configs',
'type' => MENU_LOCAL_TASK,
'file' => 'hierarchical_select.admin.inc',
);
$items['admin/config/content/hierarchical_select/implementations'] = array(
'title' => 'Implementations',
'description' => 'Features of each Hierarchical Select implementation.',
'access arguments' => array(
'administer site configuration',
),
'page callback' => 'hierarchical_select_admin_implementations',
'type' => MENU_LOCAL_TASK,
'file' => 'hierarchical_select.admin.inc',
);
$items['admin/config/content/hierarchical_select/export/%hierarchical_select_config_id'] = array(
'title' => 'Export',
'access arguments' => array(
'administer site configuration',
),
'page callback' => 'drupal_get_form',
'page arguments' => array(
'hierarchical_select_admin_export',
5,
),
'type' => MENU_LOCAL_TASK,
'file' => 'hierarchical_select.admin.inc',
);
$items['admin/config/content/hierarchical_select/import/%hierarchical_select_config_id'] = array(
'title' => 'Import',
'access arguments' => array(
'administer site configuration',
),
'page callback' => 'drupal_get_form',
'page arguments' => array(
'hierarchical_select_admin_import',
5,
),
'type' => MENU_LOCAL_TASK,
'file' => 'hierarchical_select.admin.inc',
);
return $items;
}
function hierarchical_select_element_info() {
$types['hierarchical_select'] = array(
'#input' => TRUE,
'#process' => array(
'form_hierarchical_select_process',
),
'#theme' => array(
'hierarchical_select',
),
'#theme_wrappers' => array(
'form_element',
),
'#config' => array(
'module' => 'some_module',
'params' => array(),
'save_lineage' => 0,
'enforce_deepest' => 0,
'resizable' => 1,
'level_labels' => array(
'status' => 0,
'labels' => array(),
),
'dropbox' => array(
'status' => 0,
'title' => t('All selections'),
'limit' => 0,
'reset_hs' => 1,
'sort' => 1,
),
'editability' => array(
'status' => 0,
'item_types' => array(),
'allowed_levels' => array(),
'allow_new_levels' => 0,
'max_levels' => 3,
),
'entity_count' => array(
'enabled' => 0,
'require_entity' => 0,
'settings' => array(
'count_children' => 0,
'entity_types' => array(),
),
),
'animation_delay' => variable_get('hierarchical_select_animation_delay', 400),
'special_items' => array(),
'render_flat_select' => 0,
),
'#default_value' => -1,
);
$types['hierarchical_select_item_separator'] = array(
'#theme' => 'hierarchical_select_item_separator',
);
return $types;
}
function hierarchical_select_requirements($phase) {
$requirements = array();
if ($phase == 'runtime') {
require_once DRUPAL_ROOT . '/' . 'includes/install.inc';
drupal_load_updates();
$updates = drupal_get_schema_versions('hierarchical_select');
$current = drupal_get_installed_schema_version('hierarchical_select');
$up_to_date = end($updates) == $current;
$hierarchical_select_weight = db_query("SELECT weight FROM {system} WHERE type = :type AND name = :name", array(
':type' => 'module',
':name' => 'hierarchical_select',
))
->fetchField();
$core_overriding_modules = array(
'hs_book',
'hs_menu',
'hs_taxonomy',
);
$path_errors = array();
foreach ($core_overriding_modules as $module) {
$filename = db_query("SELECT filename FROM {system} WHERE type = :type AND name = :name", array(
':type' => 'module',
':name' => $module,
))
->fetchField();
if (strpos($filename, 'modules/') === 0) {
$module_info = drupal_parse_info_file(dirname($filename) . "/{$module}.info");
$path_errors[] = t('!module', array(
'!module' => $module_info['name'],
));
}
}
if ($up_to_date && !count($path_errors)) {
$value = t('All updates installed. HS API implementation modules correctly installed.');
$description = '';
$severity = REQUIREMENT_OK;
}
elseif ($path_errors) {
$value = t('Modules incorrectly installed!');
$description = t("The following modules implement Hierarchical Select module for Drupal\n core modules, but are installed in the wrong location. They're\n installed in core's <code>modules</code> directory, but should be\n installed in either the <code>sites/all/modules</code> directory or a\n <code>sites/yoursite.com/modules</code> directory") . ':' . theme('item_list', array(
'items' => $path_errors,
));
$severity = REQUIREMENT_ERROR;
}
else {
$value = t('Not all updates installed!');
$description = t('Please run update.php to install the latest updates!
You have installed update !installed_update, but the latest update is
!latest_update!', array(
'!installed_update' => $current,
'!latest_update' => end($updates),
));
$severity = REQUIREMENT_ERROR;
}
$requirements['hierarchical_select'] = array(
'title' => t('Hierarchical Select'),
'value' => $value,
'description' => $description,
'severity' => $severity,
);
}
return $requirements;
}
function hierarchical_select_theme() {
return array(
'hierarchical_select_form_element' => array(
'file' => 'includes/theme.inc',
'variables' => array(
'element' => NULL,
'value' => NULL,
),
),
'hierarchical_select' => array(
'file' => 'includes/theme.inc',
'render element' => 'element',
),
'hierarchical_select_selects_container' => array(
'file' => 'includes/theme.inc',
'render element' => 'element',
),
'hierarchical_select_select' => array(
'file' => 'includes/theme.inc',
'render element' => 'element',
),
'hierarchical_select_item_separator' => array(
'file' => 'includes/theme.inc',
'render element' => 'element',
),
'hierarchical_select_special_option' => array(
'file' => 'includes/theme.inc',
'variables' => array(
'option' => NULL,
),
),
'hierarchical_select_dropbox_table' => array(
'file' => 'includes/theme.inc',
'render element' => 'element',
),
'hierarchical_select_common_config_form_level_labels' => array(
'file' => 'includes/theme.inc',
'render element' => 'form',
),
'hierarchical_select_common_config_form_editability' => array(
'file' => 'includes/theme.inc',
'render element' => 'form',
),
'hierarchical_select_selection_as_lineages' => array(
'file' => 'includes/theme.inc',
'variables' => array(
'selection' => NULL,
'config' => NULL,
),
),
);
}
function hierarchical_select_features_api() {
return array(
'hierarchical_select' => array(
'name' => t('Hierarchical select configs'),
'feature_source' => TRUE,
'default_hook' => 'hierarchical_select_default_configs',
'default_file' => FEATURES_DEFAULTS_INCLUDED,
'file' => drupal_get_path('module', 'hierarchical_select') . '/hierarchical_select.features.inc',
),
);
}
function hierarchical_select_menu_site_status_alter(&$menu_site_status, $path) {
global $language;
if (0 === strpos($_GET['q'], 'hierarchical_select_ajax') && !empty($_POST['hs_current_language'])) {
$languages = language_list();
if (isset($languages[$_POST['hs_current_language']])) {
$language = $languages[$_POST['hs_current_language']];
}
}
}
function hierarchical_select_config_id_load($config_id) {
$config = variable_get('hs_config_' . $config_id, FALSE);
return $config !== FALSE ? $config['config_id'] : FALSE;
}
function hierarchical_select_ajax() {
$form_parents = func_get_args();
list($form, $form_state, $form_id, $form_build_id, $commands) = ajax_get_form();
drupal_process_form($form['#form_id'], $form, $form_state);
$element = drupal_array_get_nested_value($form, $form_parents);
$output = theme('status_messages') . drupal_render($element);
$commands[] = array(
'command' => 'hierarchicalSelectUpdate',
'output' => $output,
);
$new_settings = _hs_new_setting_ajax(FALSE);
foreach ($new_settings as $new_setting) {
$commands[] = array(
'command' => 'hierarchicalSelectSettingsUpdate',
'hsid' => $new_setting['hsid'],
'settings' => $new_setting['settings'],
);
}
$context = array(
'form' => $form,
'form_state' => $form_state,
'element' => $element,
);
drupal_alter('hierarchical_select_ajax_commands', $commands, $context);
return array(
'#type' => 'ajax',
'#commands' => $commands,
);
}
function _hs_process_determine_hsid($element, &$form_state) {
if (!isset($element['#value']) || !is_array($element['#value']) || !array_key_exists('hsid', $element['#value'])) {
$hsid = uniqid();
}
else {
$hsid = check_plain($element['#value']['hsid']);
}
return $hsid;
}
function _hs_process_shortcut_special_items($config) {
$special_items = array();
if (isset($config['special_items'])) {
$special_items['exclusive'] = array_keys(array_filter($config['special_items'], '_hierarchical_select_special_item_exclusive'));
$special_items['none'] = array_keys(array_filter($config['special_items'], '_hierarchical_select_special_item_none'));
}
return $special_items;
}
function _hs_process_attach_css_js($element, $hsid, &$form_state, $complete_form) {
global $language;
$element['#attached']['library'][] = array(
'system',
'ui',
);
$element['#attached']['library'][] = array(
'system',
'drupal.ajax',
);
$element['#attached']['library'][] = array(
'system',
'jquery.form',
);
$element['#attached']['library'][] = array(
'system',
'effects',
);
$element['#attached']['library'][] = array(
'system',
'effects.drop',
);
$element['#attached']['css'][] = drupal_get_path('module', 'hierarchical_select') . '/hierarchical_select.css';
$element['#attached']['js'][] = drupal_get_path('module', 'hierarchical_select') . '/hierarchical_select.js';
if (variable_get('hierarchical_select_js_cache_system', 0) == 1) {
$element['#attached']['js'][] = drupal_get_path('module', 'hierarchical_select') . '/hierarchical_select_cache.js';
}
if (!isset($form_state['storage']['hs']['js_settings_sent'])) {
$form_state['storage']['hs']['js_settings_sent'] = array();
}
if ($form_state['process_input'] === TRUE) {
$form_state['storage']['hs']['js_settings_sent'] = array();
}
if (!isset($form_state['storage']['hs']['js_settings_sent'][$hsid]) || isset($form_state['storage']['hs']['js_settings_sent'][$hsid]) && (isset($form_state['triggering_element']) && $form_state['triggering_element']['#type'] == 'submit')) {
$config = _hierarchical_select_inherit_default_config($element['#config']);
$settings = array(
'HierarchicalSelect' => array(
'hs_current_language' => $language->language,
'settings' => array(
"hs-{$hsid}" => array(
'animationDelay' => $config['animation_delay'] == 0 ? (int) variable_get('hierarchical_select_animation_delay', 400) : $config['animation_delay'],
'cacheId' => $config['module'] . '_' . md5(serialize($config['params'])),
'renderFlatSelect' => isset($config['render_flat_select']) ? (int) $config['render_flat_select'] : 0,
'createNewItems' => isset($config['editability']['status']) ? (int) $config['editability']['status'] : 0,
'createNewLevels' => isset($config['editability']['allow_new_levels']) ? (int) $config['editability']['allow_new_levels'] : 0,
'resizable' => isset($config['resizable']) ? (int) $config['resizable'] : 0,
'ajax_url' => url('hierarchical_select_ajax/' . implode('/', $element['#array_parents'])),
),
),
),
);
if (!isset($_POST['hsid'])) {
$element['#attached']['js'][] = array(
'type' => 'setting',
'data' => $settings,
);
}
else {
$element['#attached']['_hs_new_setting_ajax'][] = array(
$hsid,
$settings['HierarchicalSelect']['settings']["hs-{$hsid}"],
);
}
$form_state['storage']['hs']['js_settings_sent'][$hsid] = TRUE;
}
return $element;
}
function _hs_new_setting_ajax($hsid = FALSE, $settings = NULL) {
static $hs_settings = array();
if ($hsid !== FALSE) {
$hs_settings[] = array(
'hsid' => $hsid,
'settings' => $settings,
);
}
return $hs_settings;
}
function _hs_process_developer_mode_log_diagnostics(&$element) {
if (HS_DEVELOPER_MODE) {
$config = $element['#config'];
$diagnostics = array();
if (!isset($config['module']) || empty($config['module'])) {
$diagnostics[] = t("'module is not set!");
}
elseif (!module_exists($config['module'])) {
$diagnostics[] = t('the module that should be used (module) is not installed!', array(
'%module' => $config['module'],
));
}
else {
$required_params = module_invoke($config['module'], 'hierarchical_select_params');
$missing_params = array_diff($required_params, array_keys($config['params']));
if (!empty($missing_params)) {
$diagnostics[] = t("'params' is missing values for: ") . implode(', ', $missing_params) . '.';
}
}
$config_id = isset($config['config_id']) && is_string($config['config_id']) ? $config['config_id'] : 'none';
if (empty($diagnostics)) {
_hierarchical_select_log("Config diagnostics (config id: {$config_id}): no problems found!");
}
else {
$diagnostics_string = print_r($diagnostics, TRUE);
$message = "Config diagnostics (config id: {$config_id}): {$diagnostics_string}";
_hierarchical_select_log($message);
$title = $element['#title'];
$element = array();
$element['#type'] = 'item';
$element['#title'] = $title;
$element['#markup'] = '<p><span style="color:red;">Fix the indicated errors in the #config property first!</span><br />' . nl2br($message) . '</p>';
return FALSE;
}
}
return TRUE;
}
function _hs_process_developer_mode_log_selections($config, $hs_selection, $db_selection) {
if (HS_DEVELOPER_MODE) {
_hierarchical_select_log("Calculated hierarchical select selection:");
_hierarchical_select_log($hs_selection);
if ($config['dropbox']['status']) {
_hierarchical_select_log("Calculated dropbox selection:");
_hierarchical_select_log($db_selection);
}
}
}
function _hs_process_developer_mode_log_hierarchy_and_dropbox($config, $hierarchy, $dropbox) {
if (HS_DEVELOPER_MODE) {
_hierarchical_select_log('Generated hierarchy in ' . $hierarchy->build_time['total'] . ' ms:');
_hierarchical_select_log($hierarchy);
if ($config['dropbox']['status']) {
_hierarchical_select_log('Generated dropbox in ' . $dropbox->build_time . ' ms: ');
_hierarchical_select_log($dropbox);
}
}
}
function _hs_process_developer_mode_send_log_js($element, $hsid) {
if (HS_DEVELOPER_MODE) {
$log = _hierarchical_select_log(NULL, TRUE);
$settings = array(
'HierarchicalSelect' => array(
'initialLog' => array(
"hs-{$hsid}" => $log,
),
),
);
$element['#attached']['js'][] = array(
'type' => 'setting',
'data' => $settings,
);
}
return $element;
}
function _hs_process_exclusive_lineages($element, $hs_selection, $db_selection) {
$config = $element['#config'];
$special_items = _hs_process_shortcut_special_items($config);
if (!empty($special_items) && count($special_items['exclusive']) && $config['dropbox']['status']) {
$selection = !empty($hs_selection) ? $hs_selection : $db_selection;
$exclusive_item = array_intersect($selection, $special_items['exclusive']);
if (count($exclusive_item)) {
$element['#config']['dropbox']['status'] = 0;
$hs_selection = array(
0 => reset($exclusive_item),
);
$db_selection = array();
}
}
return array(
$element,
$hs_selection,
$db_selection,
);
}
function _hs_process_render_create_new_item($element, $hierarchy) {
$creating_new_item = FALSE;
$element['hierarchical_select']['create_new_item'] = array(
'#prefix' => '<div class="create-new-item">',
'#suffix' => '</div>',
'#after_build' => array(
'hierarchical_select_create_new_item_after_build',
),
);
$element['hierarchical_select']['create_new_item']['create'] = array(
'#type' => 'submit',
'#value' => t('Create'),
'#attributes' => array(
'class' => array(
'create-new-item-create',
),
),
'#limit_validation_errors' => array(
$element['#parents'],
),
'#validate' => array(),
'#submit' => array(
'hierarchical_select_ajax_update_submit',
),
);
$element['hierarchical_select']['create_new_item']['cancel'] = array(
'#type' => 'submit',
'#value' => t('Cancel'),
'#attributes' => array(
'class' => array(
'create-new-item-cancel',
),
),
'#limit_validation_errors' => array(
$element['#parents'],
),
'#validate' => array(),
'#submit' => array(
'hierarchical_select_ajax_update_submit',
),
);
if (isset($element['#value']['hierarchical_select']['selects'])) {
foreach ($element['#value']['hierarchical_select']['selects'] as $depth => $value) {
if ($value == 'create_new_item' && _hierarchical_select_create_new_item_is_allowed($element['#config'], $depth)) {
$creating_new_item = TRUE;
if ($depth == 0) {
unset($element['hierarchical_select']['selects']);
}
else {
for ($i = $depth; $i < count($hierarchy->lineage); $i++) {
unset($element['hierarchical_select']['selects'][$i]);
}
}
$item_type_depth = $value == 'create_new_item' ? $depth : $depth + 1;
$item_type = count($element['#config']['editability']['item_types']) == $item_type_depth ? t($element['#config']['editability']['item_types'][$item_type_depth]) : t('item');
$element['hierarchical_select']['create_new_item']['input'] = array(
'#type' => 'textfield',
'#size' => 20,
'#maxlength' => 255,
'#default_value' => t('new @item', array(
'@item' => $item_type,
)),
'#attributes' => array(
'title' => t('new @item', array(
'@item' => $item_type,
)),
'class' => array(
'create-new-item-input',
),
),
'#theme_wrappers' => array(),
'#weight' => -1,
);
}
}
}
$element['hierarchical_select']['create_new_item']['#creating_new_item'] = $creating_new_item;
return array(
$element,
$creating_new_item,
);
}
function hierarchical_select_create_new_item_after_build(array $element) {
$element['#access'] = $element['#creating_new_item'];
return $element;
}
function _hs_process_render_dropbox($element, $hsid, $creating_new_item, $dropbox, $form_state) {
$config = $element['#config'];
if ($config['dropbox']['status']) {
if (!$creating_new_item) {
$element['hierarchical_select']['dropbox_add'] = array(
'#type' => 'submit',
'#value' => t('Add'),
'#attributes' => array(
'class' => array(
'add-to-dropbox',
),
),
'#limit_validation_errors' => array(
$element['#parents'],
),
'#validate' => array(),
'#submit' => array(
'hierarchical_select_ajax_update_submit',
),
);
}
if ($config['dropbox']['limit'] > 0) {
if (count($dropbox->lineages) >= $config['dropbox']['limit']) {
$element['dropbox_limit_warning'] = array(
'#markup' => t("You've reached the maximum number of items you can select."),
'#prefix' => '<p class="hierarchical-select-dropbox-limit-warning">',
'#suffix' => '</p>',
);
$element['hierarchical_select']['dropbox_add']['#attributes']['disabled'] = TRUE;
}
}
if (isset($dropbox->lineages_selections)) {
$form_state['storage']['hs'][$hsid]['dropbox_lineages_selections'] = $dropbox->lineages_selections;
}
$element['dropbox']['visible'] = _hs_process_render_db_table($hsid, $dropbox);
}
return array(
$element,
$form_state,
);
}
function _hs_process_render_nojs($element, $config) {
$element['nojs'] = array(
'#prefix' => '<div class="nojs">',
'#suffix' => '</div>',
);
$element['nojs']['update_button'] = array(
'#type' => 'submit',
'#value' => t('Update'),
'#attributes' => array(
'class' => array(
'update-button',
),
),
'#limit_validation_errors' => array(
$element['#parents'],
),
'#validate' => array(),
'#submit' => array(
'hierarchical_select_ajax_update_submit',
),
'#ajax' => array(
'callback' => 'menu_link_weight_parent_ajax_callback',
'wrapper' => 'menu-link-weight-wrapper',
),
);
$element['nojs']['update_button_help_text'] = array(
'#markup' => _hierarchical_select_nojs_helptext($config['dropbox']['status']),
'#prefix' => '<div class="help-text">',
'#suffix' => '</div>',
);
return $element;
}
function form_hierarchical_select_process($element, &$form_state, $complete_form) {
if (arg(0) != 'hierarchical_select_ajax') {
$cid = isset($element['#parents']) ? implode("-", $element['#parents']) : implode("-", $element['#field_parents']);
$elhsid = drupal_array_get_nested_value($element, array(
'#value',
'hsid',
));
if (!isset($elhsid)) {
$cached = drupal_array_get_nested_value($form_state, array(
'storage',
'hs',
'hs_fields',
$cid,
));
}
if (empty($cached)) {
$docache = TRUE;
}
else {
return $cached;
}
}
$hsid = _hs_process_determine_hsid($element, $form_state);
$config = $element['#config'];
$element = _hs_process_attach_css_js($element, $hsid, $form_state, $complete_form);
if (!_hs_process_developer_mode_log_diagnostics($element)) {
return $element;
}
$hs_selection = $db_selection = array();
list($hs_selection, $db_selection) = _hierarchical_select_process_calculate_selections($element, $hsid, $form_state);
_hs_process_developer_mode_log_selections($config, $hs_selection, $db_selection);
list($element, $hs_selection, $db_selection) = _hs_process_exclusive_lineages($element, $hs_selection, $db_selection);
$config = $element['#config'];
$dropbox = !$config['dropbox']['status'] ? FALSE : _hierarchical_select_dropbox_generate($config, $db_selection);
$hierarchy = _hierarchical_select_hierarchy_generate($config, $hs_selection, $element['#required'], $dropbox);
_hs_process_developer_mode_log_hierarchy_and_dropbox($config, $hierarchy, $dropbox);
$element['#return_value'] = _hierarchical_select_process_calculate_return_value($hierarchy, $config['dropbox']['status'] ? $dropbox : FALSE, $config['module'], $config['params'], $config['save_lineage']);
if (!is_array($element['#return_value'])) {
$element['#return_value'] = array(
$element['#return_value'],
);
}
$element['#element_validate'] = isset($element['#element_validate']) ? $element['#element_validate'] : array();
$element['#element_validate'] = array_merge(array(
'_hierarchical_select_validate',
), $element['#element_validate']);
$form_state['cache'] = TRUE;
$element['#tree'] = TRUE;
$element['hsid'] = array(
'#type' => 'hidden',
'#value' => $hsid,
);
if ($config['render_flat_select']) {
$element['flat_select'] = _hs_process_render_flat_select($hierarchy, $dropbox, $config);
if (empty($element['flat_select']['#options'])) {
unset($element['flat_select']);
}
}
$element['hierarchical_select'] = array(
'#theme' => 'hierarchical_select_selects_container',
);
$size = isset($element['#size']) ? $element['#size'] : 0;
$element['hierarchical_select']['selects'] = _hs_process_render_hs_selects($hsid, $hierarchy, $size);
list($element, $creating_new_item) = _hs_process_render_create_new_item($element, $hierarchy);
list($element, $form_state) = _hs_process_render_dropbox($element, $hsid, $creating_new_item, $dropbox, $form_state);
$element = _hs_process_render_nojs($element, $config);
$element['hierarchical_select']['#weight'] = 0;
$element['dropbox_limit_warning']['#weight'] = 1;
$element['dropbox']['#weight'] = 2;
$element['nojs']['#weight'] = 3;
if (isset($element['#disabled']) && $element['#disabled']) {
_hierarchical_select_mark_as_disabled($element);
}
if (empty($docache)) {
if (!isset($form_state['triggering_element']) || $form_state['triggering_element']['#value'] != t('Preview') && $form_state['triggering_element']['#value'] != t('View changes')) {
if (isset($form_state['input']) && is_array($form_state['input'])) {
drupal_array_set_nested_value($form_state['input'], $element['#array_parents'], array());
}
}
}
else {
$form_state['storage']['hs']['hs_fields'][$cid] = $element;
}
$element = _hs_process_developer_mode_send_log_js($element, $hsid);
return $element;
}
function hierarchical_select_ajax_update_submit($form, &$form_state) {
$form_state['no_redirect'] = TRUE;
}
function _hierarchical_select_validate(&$element, &$form_state) {
$hsid = $element['hsid']['#value'];
$config = _hierarchical_select_inherit_default_config($element['#config']);
if ($config['dropbox']['status']) {
if ($config['dropbox']['limit'] > 0) {
$lineage_count = count($form_state['storage']['hs'][$hsid]['dropbox_lineages_selections']);
if ($lineage_count > $config['dropbox']['limit']) {
form_error($element, t("You've selected %lineage-count items, but you're only allowed to select %dropbox-limit items.", array(
'%lineage-count' => $lineage_count,
'%dropbox-limit' => $config['dropbox']['limit'],
)));
_hierarchical_select_form_set_error_class($element);
}
}
}
if (isset($element['#disabled']) && $element['#disabled']) {
$element['#return_value'] = $element['#default_value'];
}
$element['#value'] = $element['#return_value'];
form_set_value($element, $element['#value'], $form_state);
if ($element['#required'] && (!isset($form_state['submit_handlers'][0]) || $form_state['submit_handlers'][0] !== 'hierarchical_select_ajax_update_submit') && (!count($element['#value']) || is_string($element['#value']) && strlen(trim($element['#value'])) == 0)) {
form_error($element, t('!name field is required.', array(
'!name' => $element['#title'],
)));
_hierarchical_select_form_set_error_class($element);
}
}
function _hierarchical_select_process_get_hs_selection($element) {
$hs_selection = array();
$config = _hierarchical_select_inherit_default_config($element['#config']);
if (!empty($element['#value']['hierarchical_select']['selects'])) {
if ($config['save_lineage']) {
foreach ($element['#value']['hierarchical_select']['selects'] as $key => $value) {
$hs_selection[] = $value;
}
}
else {
foreach ($element['#value']['hierarchical_select']['selects'] as $key => $value) {
$hs_selection[] = $value;
}
$hs_selection = _hierarchical_select_hierarchy_validate($hs_selection, $config['module'], $config['params']);
$hs_selection = $hs_selection != -1 ? array(
end($hs_selection),
) : array();
}
}
return $hs_selection;
}
function _hierarchical_select_process_get_db_selection($element, $hsid, &$form_state) {
$db_selection = array();
if (!empty($form_state['storage']['hs'][$hsid]['dropbox_lineages_selections'])) {
$remove_from_db_selection = array();
if (isset($element['#value']['dropbox']['visible']['lineages'])) {
foreach ($element['#value']['dropbox']['visible']['lineages'] as $x => $remove_value) {
if ($remove_value['remove'] === '1') {
$remove_from_db_selection[] = substr($x, 8);
$elm =& $form_state['input'];
foreach ($element['#parents'] as $parent) {
$elm =& $elm[$parent];
}
unset($elm['dropbox']['visible']['lineages'][$x]['remove']);
}
}
}
foreach ($form_state['storage']['hs'][$hsid]['dropbox_lineages_selections'] as $x => $selection) {
if (!in_array($x, $remove_from_db_selection)) {
$db_selection = array_merge($db_selection, $selection);
}
}
foreach ($remove_from_db_selection as $key => $x) {
$item = end($form_state['storage']['hs'][$hsid]['dropbox_lineages_selections'][$x]);
$position = array_search($item, $db_selection);
if ($position) {
unset($db_selection[$position]);
}
}
$db_selection = array_unique($db_selection);
}
return $db_selection;
}
function _hierarchical_select_process_calculate_selections(&$element, $hsid, &$form_state) {
$hs_selection = array();
$db_selection = array();
$config = _hierarchical_select_inherit_default_config($element['#config']);
$dropbox = (bool) $config['dropbox']['status'];
if (empty($form_state['input']) || !isset($element['#value']['hierarchical_select']) && !isset($element['#value']['dropbox'])) {
$value = !empty($element['#value']) ? $element['#value'] : $element['#default_value'];
$value = is_array($value) ? $value : array(
$value,
);
if ($dropbox) {
$db_selection = $value;
}
else {
$hs_selection = $value;
}
}
else {
$op = isset($form_state['input']['op']) && isset($form_state['input']['hsid']) && $form_state['input']['hsid'] == $hsid ? $form_state['input']['op'] : NULL;
if ($dropbox && $op == t('Add')) {
$hs_selection = _hierarchical_select_process_get_hs_selection($element);
$db_selection = _hierarchical_select_process_get_db_selection($element, $hsid, $form_state);
$db_selection = array_unique(array_merge($db_selection, $hs_selection));
if ((bool) $config['dropbox']['reset_hs']) {
$hs_selection = array();
}
}
elseif ($op == t('Create')) {
$label = trim($element['#value']['hierarchical_select']['create_new_item']['input']);
$selects = isset($element['#value']['hierarchical_select']['selects']) ? $element['#value']['hierarchical_select']['selects'] : array();
$depth = count($selects);
$parent = $depth > 0 ? end($selects) : 0;
if (empty($label)) {
$element['#value']['hierarchical_select']['selects'][count($selects)] = 'create_new_item';
}
elseif ((count(module_invoke($config['module'], 'hierarchical_select_children', $parent, $config['params'])) || $config['editability']['max_levels'] == 0 && $config['allowed_max_depth'] == 0 || $config['editability']['max_levels'] == 0 && $depth < $config['allowed_max_depth'] || $depth < $config['editability']['max_levels'] && $config['allowed_max_depth'] == 0 || $depth < $config['editability']['max_levels'] && $depth < $config['allowed_max_depth']) && _hierarchical_select_create_new_item_is_allowed($config, $depth)) {
$value = module_invoke($config['module'], 'hierarchical_select_create_item', check_plain($label), $parent, $config['params']);
if ($value) {
$element['#value']['hierarchical_select']['selects'][count($selects)] = $value;
}
}
$hs_selection = _hierarchical_select_process_get_hs_selection($element);
if ($dropbox) {
$db_selection = _hierarchical_select_process_get_db_selection($element, $hsid, $form_state);
}
}
else {
$hs_selection = _hierarchical_select_process_get_hs_selection($element);
if ($dropbox) {
$db_selection = _hierarchical_select_process_get_db_selection($element, $hsid, $form_state);
}
}
}
$hs_selection = array_unique($hs_selection, SORT_REGULAR);
$db_selection = array_unique($db_selection, SORT_REGULAR);
return array(
$hs_selection,
$db_selection,
);
}
function _hs_process_render_hs_selects($hsid, $hierarchy, $size) {
$form['#tree'] = TRUE;
$form['#prefix'] = '<div class="selects">';
$form['#suffix'] = '</div>';
foreach ($hierarchy->lineage as $depth => $selected_item) {
$form[$depth] = array(
'#type' => 'select',
'#options' => $hierarchy->levels[$depth],
'#default_value' => $selected_item,
'#size' => $size,
'#theme_wrappers' => array(),
'#theme' => 'hierarchical_select_select',
'#childinfo' => isset($hierarchy->childinfo[$depth]) ? $hierarchy->childinfo[$depth] : NULL,
'#validated' => TRUE,
);
}
return $form;
}
function _hs_process_render_db_table($hsid, $dropbox) {
$element['#tree'] = TRUE;
$element['#theme'] = 'hierarchical_select_dropbox_table';
$element['title'] = array(
'#type' => 'value',
'#value' => t($dropbox->title),
);
$element['separator'] = array(
'#type' => 'value',
'#value' => '›',
);
$element['is_empty'] = array(
'#type' => 'value',
'#value' => empty($dropbox->lineages),
);
if (!empty($dropbox->lineages)) {
foreach ($dropbox->lineages as $x => $lineage) {
$element['lineages']["lineage-{$x}"] = array(
'#zebra' => ($x + 1) % 2 == 0 ? 'even' : 'odd',
'#first' => $x == 0 ? 'first' : '',
'#last' => $x == count($dropbox->lineages) - 1 ? 'last' : '',
);
foreach ($lineage as $depth => $item) {
$is_selected = $dropbox->save_lineage || $depth == count($lineage) - 1;
$element['lineages']["lineage-{$x}"][$depth] = array(
'#markup' => $item['label'],
'#prefix' => '<span class="dropbox-item' . ($is_selected ? ' dropbox-selected-item' : '') . '">',
'#suffix' => '</span>',
);
}
$element['lineages']["lineage-{$x}"]['remove'] = array(
'#type' => 'checkbox',
'#title' => t('Remove'),
);
}
}
return $element;
}
function _hs_process_render_flat_select($hierarchy, $dropbox, $config) {
$selection = array();
if ($config['dropbox']['status']) {
foreach ($dropbox->lineages_selections as $lineage_selection) {
$selection = array_merge($selection, $lineage_selection);
}
}
else {
$selection = $hierarchy->lineage;
}
$options = array();
foreach ($selection as $value) {
$is_valid = module_invoke($config['module'], 'hierarchical_select_valid_item', $value, $config['params']);
if ($is_valid) {
$options[$value] = $value;
}
}
$element = array(
'#type' => 'select',
'#multiple' => $config['save_lineage'] || $config['dropbox']['status'],
'#options' => $options,
'#value' => array_keys($options),
'#theme' => 'hierarchical_select_select',
'#attributes' => array(
'class' => array(
'flat-select',
),
),
);
return $element;
}
function _hierarchical_select_process_calculate_return_value($hierarchy, $dropbox = FALSE, $module, $params, $save_lineage) {
if (!$dropbox) {
$return_value = _hierarchical_select_hierarchy_validate($hierarchy->lineage, $module, $params);
if (!$save_lineage) {
$return_value = is_array($return_value) ? end($return_value) : NULL;
}
$return_value = $return_value != -1 ? $return_value : NULL;
}
else {
$return_value = array();
foreach ($dropbox->lineages_selections as $x => $selection) {
if (!$save_lineage) {
$return_value[] = end($selection);
}
else {
$lineage = _hierarchical_select_hierarchy_validate($selection, $module, $params);
$return_value = array_merge($return_value, $lineage);
}
}
$return_value = array_unique($return_value);
}
return $return_value;
}
function _hierarchical_select_inherit_default_config($config, $defaults_override = array()) {
$type = hierarchical_select_element_info();
$defaults = $type['hierarchical_select']['#config'];
unset($defaults['module']);
unset($defaults['params']);
$defaults = array_smart_merge($defaults, $defaults_override);
$config = array_smart_merge($defaults, $config);
return $config;
}
function _hierarchical_select_json_convert_hierarchy_to_cache($hierarchy) {
$cache = array();
foreach ($hierarchy->levels as $depth => $items) {
$weight = 0;
foreach ($items as $value => $label) {
$weight++;
$cache[] = array(
'value' => $value,
'label' => $label,
'parent' => $depth == 0 ? 0 : $hierarchy->lineage[$depth - 1],
'weight' => $weight,
);
}
}
$value = end($hierarchy->lineage);
$cache[] = array(
'value' => $value . '-has-no-children',
'label' => '',
'parent' => $value,
'weight' => 0,
);
return $cache;
}
function _hierarchical_select_mark_as_disabled(&$element) {
$element['#attributes']['disabled'] = TRUE;
foreach (element_children($element) as $key) {
if (isset($element[$key]) && $element[$key]) {
_hierarchical_select_mark_as_disabled($element[$key]);
}
}
}
function _hierarchical_select_create_new_item_is_allowed($config, $depth) {
return isset($config['editability']['allowed_levels'][$depth]) ? $config['editability']['allowed_levels'][$depth] : 1;
}
function _hierarchical_select_nojs_helptext($dropbox_is_enabled) {
$output = '<noscript>';
$items = array(
t('<span class="highlight">enable Javascript</span> in your browser and then refresh this page, for a much enhanced experience.'),
t('<span class="highlight">click the <em>Update</em> button</span> every time you want to update the selection'),
);
$items[1] .= !$dropbox_is_enabled ? '.' : t(", or when you've checked some checkboxes for entries in the dropbox you'd like to remove.");
$output .= '<span class="warning">';
$output .= t("You don't have Javascript enabled.");
$output .= '</span> ';
$output .= '<span class="ask-to-hover">';
$output .= t('Hover for more information!');
$output .= '</span> ';
$output .= t("But don't worry: you can still use this web site! You have two options:");
$output .= theme('item_list', array(
'items' => $items,
'title' => NULL,
'type' => 'ul',
'attributes' => array(
'class' => array(
'solutions',
),
),
));
$output .= '</noscript>';
return $output;
}
function _hierarchical_select_form_set_error_class(&$element) {
$config = _hierarchical_select_inherit_default_config($element['#config']);
if ($config['dropbox']['status']) {
form_error($element['dropbox']['visible']);
}
else {
for ($i = 0; $i < count(element_children($element['hierarchical_select']['selects'])); $i++) {
form_error($element['hierarchical_select']['selects'][$i]);
}
}
}
function _hierarchical_select_log($item, $reset = FALSE) {
static $log;
if ($reset) {
$copy_of_log = $log;
$log = array();
return $copy_of_log;
}
$log[] = $item;
}
function _hierarchical_select_hierarchy_generate($config, $selection, $required, $dropbox = FALSE) {
$hierarchy = new stdClass();
if (isset($config['special_items'])) {
$special_items['exclusive'] = array_keys(array_filter($config['special_items'], '_hierarchical_select_special_item_exclusive'));
$special_items['none'] = array_keys(array_filter($config['special_items'], '_hierarchical_select_special_item_none'));
}
$start_lineage = microtime(TRUE);
if ($config['save_lineage'] && is_array($selection) && count($selection) >= 2) {
$root_level = array_keys(module_invoke($config['module'], 'hierarchical_select_root_level', $config['params']));
for ($i = 0; $i < count($selection); $i++) {
if (in_array($selection[$i], $root_level)) {
if ($i != 0) {
list($selection[0], $selection[$i]) = array(
$selection[$i],
$selection[0],
);
}
break;
}
}
for ($i = 0; $i < count($selection); $i++) {
$children = array_keys(module_invoke($config['module'], 'hierarchical_select_children', $selection[$i], $config['params']));
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],
);
}
}
}
}
$selection = _hierarchical_select_hierarchy_validate($selection, $config['module'], $config['params']);
if ($selection == -1) {
$root_level = module_invoke($config['module'], 'hierarchical_select_root_level', $config['params']);
$first_case = $config['enforce_deepest'] && $config['level_labels']['status'] && !isset($config['level_labels']['labels'][0]);
$second_case = $dropbox && count($dropbox->lineages) > 0;
$none_option = isset($special_items) && count($special_items['none']) ? $special_items['none'][0] : 'none';
$hierarchy->lineage[0] = $first_case || $second_case ? $none_option : 'label_0';
}
else {
if ($config['save_lineage']) {
$hierarchy->lineage = is_array($selection) ? $selection : array(
0 => $selection,
);
}
else {
$selection = is_array($selection) ? $selection[0] : $selection;
if (module_invoke($config['module'], 'hierarchical_select_valid_item', $selection, $config['params'])) {
$hierarchy->lineage = module_invoke($config['module'], 'hierarchical_select_lineage', $selection, $config['params']);
}
else {
$hierarchy->lineage = array();
}
}
}
if ($config['enforce_deepest'] && !in_array($hierarchy->lineage[0], array(
'none',
'label_0',
))) {
$hierarchy->lineage = _hierarchical_select_hierarchy_enforce_deepest($hierarchy->lineage, $config['module'], $config['params']);
}
$end_lineage = microtime(TRUE);
$start_levels = microtime(TRUE);
$hierarchy->levels[0] = module_invoke($config['module'], 'hierarchical_select_root_level', $config['params']);
$hierarchy->levels[0] = _hierarchical_select_apply_entity_settings($hierarchy->levels[0], $config);
if (!empty($config['editability']['status']) && module_hook($config['module'], 'hierarchical_select_create_item') && ($config['module'] == 'hs_taxonomy' && (user_access('administer taxonomy') || user_access('edit terms in ' . $config['params']['vid']))) && _hierarchical_select_create_new_item_is_allowed($config, 0)) {
$item_type = isset($config['editability']['item_types']) && count($config['editability']['item_types']) > 0 ? t($config['editability']['item_types'][0]) : t('item');
$option = theme('hierarchical_select_special_option', array(
'option' => t('create new !item_type', array(
'!item_type' => $item_type,
)),
));
$hierarchy->levels[0] = array(
'create_new_item' => $option,
) + $hierarchy->levels[0];
}
$first_case = !$required;
$second_case = $config['enforce_deepest'];
$third_case = $dropbox && count($dropbox->lineages) > 0;
if (($first_case || $second_case || $third_case) && (!$config['level_labels']['status'] && isset($special_items) && !count($special_items['none']))) {
$option = theme('hierarchical_select_special_option', array(
'option' => t('none'),
));
$hierarchy->levels[0] = array(
'none' => $option,
) + $hierarchy->levels[0];
}
$max_depth = count($hierarchy->lineage) - 1;
for ($depth = 1; $depth <= $max_depth; $depth++) {
$hierarchy->levels[$depth] = module_invoke($config['module'], 'hierarchical_select_children', $hierarchy->lineage[$depth - 1], $config['params']);
$hierarchy->levels[$depth] = _hierarchical_select_apply_entity_settings($hierarchy->levels[$depth], $config);
}
if ($config['enforce_deepest']) {
if (!empty($config['editability']['status']) && ($config['module'] == 'hs_taxonomy' && (user_access('administer taxonomy') || user_access('edit terms in ' . $config['params']['vid']))) && module_hook($config['module'], 'hierarchical_select_create_item')) {
for ($depth = 1; $depth <= $max_depth; $depth++) {
$item_type = count($config['editability']['item_types']) >= $depth ? t($config['editability']['item_types'][$depth]) : t('item');
$option = theme('hierarchical_select_special_option', array(
'option' => t('create new !item_type', array(
'!item_type' => $item_type,
)),
));
if (_hierarchical_select_create_new_item_is_allowed($config, $depth)) {
$hierarchy->levels[$depth] = array(
'create_new_item' => $option,
) + $hierarchy->levels[$depth];
}
}
}
if ($config['level_labels']['status'] && isset($config['level_labels']['labels'][0])) {
$hierarchy->levels[0] = array(
'label_0' => t($config['level_labels']['labels'][0]),
) + $hierarchy->levels[0];
}
}
else {
if (!$config['enforce_deepest']) {
for ($depth = 0; $depth <= $max_depth; $depth++) {
if ($depth > 0 && !empty($config['editability']['status']) && module_hook($config['module'], 'hierarchical_select_create_item') && ($config['module'] == 'hs_taxonomy' && (user_access('administer taxonomy') || user_access('edit terms in ' . $config['params']['vid']))) && _hierarchical_select_create_new_item_is_allowed($config, $depth)) {
$item_type = count($config['editability']['item_types']) == $depth ? t($config['editability']['item_types'][$depth]) : t('item');
$option = theme('hierarchical_select_special_option', array(
'option' => t('create new !item_type', array(
'!item_type' => $item_type,
)),
));
$hierarchy->levels[$depth] = array(
'create_new_item' => $option,
) + $hierarchy->levels[$depth];
}
$label = $config['level_labels']['status'] && isset($config['level_labels']['labels'][$depth]) ? t($config['level_labels']['labels'][$depth]) : '';
$hierarchy->levels[$depth] = array(
'label_' . $depth => $label,
) + $hierarchy->levels[$depth];
}
if ($hierarchy->levels[0]['label_0'] == '' && isset($hierarchy->levels[0]['none'])) {
unset($hierarchy->levels[0]['label_0']);
if ($hierarchy->lineage[0] == 'label_0') {
$hierarchy->lineage[0] = 'none';
}
}
$parent = $hierarchy->lineage[$max_depth];
if (module_invoke($config['module'], 'hierarchical_select_valid_item', $parent, $config['params'])) {
$children = module_invoke($config['module'], 'hierarchical_select_children', $parent, $config['params']);
if (count($children)) {
$depth = $max_depth + 1;
$hierarchy->levels[$depth] = array();
if (!empty($config['editability']['status']) && module_hook($config['module'], 'hierarchical_select_create_item') && ($config['module'] == 'hs_taxonomy' && (user_access('administer taxonomy') || user_access('edit terms in ' . $config['params']['vid']))) && _hierarchical_select_create_new_item_is_allowed($config, $depth)) {
$item_type = count($config['editability']['item_types']) >= $depth ? t($config['editability']['item_types'][$depth]) : t('item');
$option = theme('hierarchical_select_special_option', array(
'option' => t('create new !item_type', array(
'!item_type' => $item_type,
)),
));
$hierarchy->levels[$depth] = array(
'create_new_item' => $option,
);
}
$hierarchy->lineage[$depth] = 'label_' . $depth;
$label = $config['level_labels']['status'] ? t($config['level_labels']['labels'][$depth]) : '';
$hierarchy->levels[$depth] = array(
'label_' . $depth => $label,
) + $hierarchy->levels[$depth] + $children;
$hierarchy->levels[$depth] = _hierarchical_select_apply_entity_settings($hierarchy->levels[$depth], $config);
}
}
}
}
if (!empty($config['editability']['status']) && !empty($config['editability']['allow_new_levels']) && ($config['editability']['max_levels'] == 0 || count($hierarchy->lineage) < $config['editability']['max_levels']) && ($config['allowed_max_depth'] == 0 || count($hierarchy->lineage) < $config['allowed_max_depth']) && module_invoke($config['module'], 'hierarchical_select_valid_item', end($hierarchy->lineage), $config['params']) && ($config['module'] == 'hs_taxonomy' && (user_access('administer taxonomy') || user_access('edit terms in ' . $config['params']['vid']))) && module_hook($config['module'], 'hierarchical_select_create_item')) {
$depth = $max_depth + 1;
$hierarchy->lineage[$depth] = 'label_' . $depth;
$label = $config['level_labels']['status'] ? t($config['level_labels']['labels'][$depth]) : '';
$item_type = count($config['editability']['item_types']) >= $depth ? t($config['editability']['item_types'][$depth]) : t('item');
$option = theme('hierarchical_select_special_option', array(
'option' => t('create new !item_type', array(
'!item_type' => $item_type,
)),
));
$hierarchy->levels[$depth] = array(
'label_' . $depth => $label,
'create_new_item' => $option,
);
}
$end_levels = microtime(TRUE);
$start_childinfo = microtime(TRUE);
$hierarchy = _hierarchical_select_hierarchy_add_childinfo($hierarchy, $config);
$end_childinfo = microtime(TRUE);
$hierarchy->build_time['total'] = ($end_childinfo - $start_lineage) * 1000;
$hierarchy->build_time['lineage'] = ($end_lineage - $start_lineage) * 1000;
$hierarchy->build_time['levels'] = ($end_levels - $start_levels) * 1000;
$hierarchy->build_time['childinfo'] = ($end_childinfo - $start_childinfo) * 1000;
return $hierarchy;
}
function _hierarchical_select_apply_entity_settings($level, $config) {
if (isset($config['special_items'])) {
$special_items['exclusive'] = array_keys(array_filter($config['special_items'], '_hierarchical_select_special_item_exclusive'));
$special_items['none'] = array_keys(array_filter($config['special_items'], '_hierarchical_select_special_item_none'));
}
if (isset($config['entity_count']['enabled']) && ($config['entity_count']['enabled'] || $config['entity_count']['require_entity']) && module_hook($config['module'], 'hierarchical_select_entity_count')) {
foreach ($level as $item => $label) {
if (!preg_match('/(none|label_\\d+|create_new_item)/', $item) && !in_array($item, $special_items['exclusive']) && !in_array($item, $special_items['none'])) {
$config['params'] += array(
'entity_count' => array(
'settings' => array(
'count_children' => $config['entity_count']['settings']['count_children'],
'entity_types' => $config['entity_count']['settings']['entity_types'],
),
),
);
$entity_count = module_invoke($config['module'], 'hierarchical_select_entity_count', $item, $config['params']);
if ($config['entity_count']['require_entity'] && $entity_count == 0) {
unset($level[$item]);
}
elseif ($config['entity_count']['enabled']) {
$level[$item] = "{$label} ({$entity_count})";
}
}
}
}
return $level;
}
function _hierarchical_select_hierarchy_add_childinfo($hierarchy, $config) {
foreach ($hierarchy->levels as $depth => $level) {
foreach (array_keys($level) as $item) {
if (!preg_match('/(none|label_\\d+|create_new_item)/', $item)) {
$hierarchy->childinfo[$depth][$item] = count(module_invoke($config['module'], 'hierarchical_select_children', $item, $config['params']));
}
}
}
return $hierarchy;
}
function _hierarchical_select_hierarchy_validate($selection, $module, $params) {
$valid = TRUE;
$selection_levels = count($selection);
for ($i = 0; $i < $selection_levels; $i++) {
if ($valid) {
$valid = module_invoke($module, 'hierarchical_select_valid_item', $selection[$i], $params);
if ($i > 0) {
$parent = $selection[$i - 1];
$child = $selection[$i];
$children = array_keys(module_invoke($module, 'hierarchical_select_children', $parent, $params));
$valid = $valid && in_array($child, $children);
}
}
if (!$valid) {
unset($selection[$i]);
}
}
if (empty($selection)) {
$selection = -1;
}
if (is_array($selection)) {
$selection = array_values($selection);
}
return $selection;
}
function _hierarchical_select_hierarchy_enforce_deepest($lineage, $module, $params) {
$parent = end($lineage);
$children = module_invoke($module, 'hierarchical_select_children', $parent, $params);
while (count($children)) {
$keys = array_keys($children);
$first_child = $keys[0];
$lineage[] = $first_child;
$parent = $first_child;
$children = module_invoke($module, 'hierarchical_select_children', $parent, $params);
}
return $lineage;
}
function _hierarchical_select_dropbox_generate($config, $selection) {
$dropbox = new stdClass();
$start = microtime(TRUE);
$dropbox->title = !empty($config['dropbox']['title']) ? filter_xss_admin($config['dropbox']['title']) : t('All selections');
$dropbox->lineages = array();
$dropbox->lineages_selections = array();
foreach ($selection as $key => $item) {
if (!module_invoke($config['module'], 'hierarchical_select_valid_item', $item, $config['params'])) {
unset($selection[$key]);
}
}
if (!empty($selection)) {
$dropbox->save_lineage = $config['save_lineage'];
if ($config['save_lineage']) {
$dropbox->lineages = _hierarchical_select_dropbox_reconstruct_lineages_save_lineage_enabled($config['module'], $selection, $config['params']);
}
else {
foreach ($selection as $item) {
$dropbox->lineages[] = module_invoke($config['module'], 'hierarchical_select_lineage', $item, $config['params']);
}
foreach ($dropbox->lineages as $id => $lineage) {
foreach ($lineage as $level => $item) {
$dropbox->lineages[$id][$level] = array(
'value' => $item,
'label' => module_invoke($config['module'], 'hierarchical_select_item_get_label', $item, $config['params']),
);
}
}
}
foreach ($dropbox->lineages as $id => $lineage) {
foreach ($lineage as $level => $item) {
$dropbox->lineages[$id][$level]['label'] = check_plain($dropbox->lineages[$id][$level]['label']);
}
}
if (!isset($config['dropbox']['sort']) || $config['dropbox']['sort']) {
usort($dropbox->lineages, '_hierarchical_select_dropbox_sort');
}
foreach ($dropbox->lineages as $id => $lineage) {
if ($config['save_lineage']) {
$dropbox->lineages_selections[$id] = array_map('_hierarchical_select_dropbox_lineage_item_get_value', $lineage);
}
else {
$dropbox->lineages_selections[$id][0] = $lineage[count($lineage) - 1]['value'];
}
}
}
$dropbox->build_time = (microtime(TRUE) - $start) * 1000;
return $dropbox;
}
function _hierarchical_select_dropbox_reconstruct_lineages_save_lineage_enabled($module, $selection, $params) {
$lineages = array();
$root_level = module_invoke($module, 'hierarchical_select_root_level', $params);
foreach ($selection as $key => $item) {
if (array_key_exists($item, $root_level)) {
$lineages[][0] = array(
'value' => $item,
'label' => $root_level[$item],
);
unset($selection[$key]);
}
}
$at_least_one = TRUE;
for ($level = 0; $at_least_one; $level++) {
$at_least_one = FALSE;
$num = count($lineages);
for ($id = 0; $id < $num; $id++) {
if (!isset($lineages[$id][$level])) {
continue;
}
$children = module_invoke($module, 'hierarchical_select_children', $lineages[$id][$level]['value'], $params);
$child_added_to_lineage = FALSE;
foreach (array_keys($children) as $child) {
if (in_array((string) $child, $selection)) {
if (!$child_added_to_lineage) {
$lineages[$id][$level + 1] = array(
'value' => $child,
'label' => $children[$child],
);
$child_added_to_lineage = TRUE;
$at_least_one = TRUE;
}
else {
$lineage = $lineages[$id];
$lineage[$level + 1] = array(
'value' => $child,
'label' => $children[$child],
);
$lineages[] = $lineage;
}
}
}
}
}
return $lineages;
}
function _hierarchical_select_dropbox_sort($lineage_a, $lineage_b) {
$string_a = implode('', array_map('_hierarchical_select_dropbox_lineage_item_get_label', $lineage_a));
$string_b = implode('', array_map('_hierarchical_select_dropbox_lineage_item_get_label', $lineage_b));
return strcmp($string_a, $string_b);
}
function _hierarchical_select_dropbox_lineage_item_get_label($item) {
return t($item['label']);
}
function _hierarchical_select_dropbox_lineage_item_get_value($item) {
return $item['value'];
}
if (!function_exists('array_smart_merge')) {
function array_smart_merge($array, $override) {
if (is_array($array) && is_array($override)) {
foreach ($override as $k => $v) {
if (isset($array[$k]) && is_array($v) && is_array($array[$k])) {
$array[$k] = array_smart_merge($array[$k], $v);
}
else {
$array[$k] = $v;
}
}
}
return $array;
}
}
function _hierarchical_select_special_item_exclusive($item) {
return in_array('exclusive', $item);
}
function _hierarchical_select_special_item_none($item) {
return in_array('none', $item);
}