/**
 * Pre-processes variables for the "bootstrap_dropdown" theme hook.
 *
 * See theme function for list of available variables.
 *
 * @see bootstrap_bootstrap_dropdown()
 *
 * @ingroup theme_preprocess
 */
function bootstrap_preprocess_bootstrap_dropdown(&$variables)
{
    $element =& $variables['element'];
    // Provide defaults.
    $element += array('#wrapper_attributes' => NULL, '#attributes' => NULL, '#alignment' => NULL, '#toggle' => NULL, '#items' => NULL);
    // Dropdown vertical alignment.
    $element['#wrapper_attributes']['class'][] = 'dropdown';
    if ($element['#alignment'] === 'up' || is_array($element['#alignment']) && in_array('up', $element['#alignment'])) {
        $element['#wrapper_attributes']['class'][] = 'dropup';
    }
    if (isset($element['#toggle'])) {
        if (is_string($element['#toggle'])) {
            $element['#toggle'] = array('#theme' => 'link__bootstrap_dropdown__toggle', '#text' => _bootstrap_filter_xss($element['#toggle']), '#path' => '#', '#options' => array('attributes' => array(), 'html' => TRUE, 'external' => TRUE));
        }
        if (isset($element['#toggle']['#options']['attributes'])) {
            $element['#toggle']['#options']['attributes']['class'][] = 'dropdown-toggle';
            $element['#toggle']['#options']['attributes']['data-toggle'] = 'dropdown';
        } else {
            $element['#toggle']['#attributes']['class'][] = 'dropdown-toggle';
            $element['#toggle']['#attributes']['data-toggle'] = 'dropdown';
        }
    }
    // Menu items.
    $element['#attributes']['role'] = 'menu';
    $element['#attributes']['class'][] = 'dropdown-menu';
    if ($element['#alignment'] === 'right' || is_array($element['#alignment']) && in_array('right', $element['#alignment'])) {
        $element['#attributes']['class'][] = 'dropdown-menu-right';
    }
}
/**
 * Overrides theme_menu_link() for book module.
 */
function bootstrap_menu_link__book_toc(array $variables)
{
    $element = $variables['element'];
    $sub_menu = drupal_render($element['#below']);
    $title = $element['#title'];
    $href = $element['#href'];
    $options = !empty($element['#localized_options']) ? $element['#localized_options'] : array();
    $attributes = !empty($element['#attributes']) ? $element['#attributes'] : array();
    $attributes['role'] = 'presentation';
    // Header.
    $link = TRUE;
    if ($title && $href === FALSE) {
        $attributes['class'][] = 'dropdown-header';
        $link = FALSE;
    } elseif ($title === FALSE && $href === FALSE) {
        $attributes['class'][] = 'divider';
        $link = FALSE;
    } elseif (($href == $_GET['q'] || $href == '<front>' && drupal_is_front_page()) && empty($options['language'])) {
        $attributes['class'][] = 'active';
    }
    // Filter the title if the "html" is set, otherwise l() will automatically
    // sanitize using check_plain(), so no need to call that here.
    if (!empty($options['html'])) {
        $title = _bootstrap_filter_xss($title);
    }
    // Convert to a link.
    if ($link) {
        $title = l($title, $href, $options);
    }
    return '<li' . drupal_attributes($attributes) . '>' . $title . $sub_menu . "</li>\n";
}
/**
 * Returns HTML for status and/or error messages, grouped by type.
 *
 * An invisible heading identifies the messages for assistive technology.
 * Sighted users see a colored box. See http://www.w3.org/TR/WCAG-TECHS/H69.html
 * for info.
 *
 * @param array $variables
 *   An associative array containing:
 *   - display: (optional) Set to 'status' or 'error' to display only messages
 *     of that type.
 *
 * @return string
 *   The constructed HTML.
 *
 * @see theme_status_messages()
 *
 * @ingroup theme_functions
 */
function bootstrap_status_messages($variables)
{
    $display = $variables['display'];
    $output = '';
    $status_heading = array('status' => t('Status message'), 'error' => t('Error message'), 'warning' => t('Warning message'), 'info' => t('Informative message'));
    // Map Drupal message types to their corresponding Bootstrap classes.
    // @see http://twitter.github.com/bootstrap/components.html#alerts
    $status_class = array('status' => 'success', 'error' => 'danger', 'warning' => 'warning', 'info' => 'info');
    // Retrieve messages.
    $message_list = drupal_get_messages($display);
    // Allow the disabled_messages module to filter the messages, if enabled.
    if (module_exists('disable_messages') && variable_get('disable_messages_enable', '1')) {
        $message_list = disable_messages_apply_filters($message_list);
    }
    foreach ($message_list as $type => $messages) {
        $class = isset($status_class[$type]) ? ' alert-' . $status_class[$type] : '';
        $output .= "<div class=\"alert alert-block{$class} messages {$type}\">\n";
        $output .= "  <a class=\"close\" data-dismiss=\"alert\" href=\"#\">&times;</a>\n";
        if (!empty($status_heading[$type])) {
            $output .= '<h4 class="element-invisible">' . _bootstrap_filter_xss($status_heading[$type]) . "</h4>\n";
        }
        if (count($messages) > 1) {
            $output .= " <ul>\n";
            foreach ($messages as $message) {
                $output .= '  <li>' . _bootstrap_filter_xss($message) . "</li>\n";
            }
            $output .= " </ul>\n";
        } else {
            $output .= _bootstrap_filter_xss($messages[0]);
        }
        $output .= "</div>\n";
    }
    return $output;
}
/**
 * Returns HTML for a single local action link.
 *
 * @param array $variables
 *   An associative array containing:
 *   - element: A render element containing:
 *     - #link: A menu link array with 'title', 'href', and 'localized_options'
 *       keys.
 *
 * @return string
 *   The constructed HTML.
 *
 * @see theme_menu_local_action()
 *
 * @ingroup theme_functions
 */
function bootstrap_menu_local_action($variables)
{
    $link = $variables['element']['#link'];
    $title = $link['title'];
    $icon = _bootstrap_iconize_text($title);
    $href = !empty($link['href']) ? $link['href'] : FALSE;
    $options = isset($link['localized_options']) ? $link['localized_options'] : array();
    // Format the action link.
    if ($href) {
        // Turn link into a mini-button and colorize based on title.
        if ($class = _bootstrap_colorize_text($title)) {
            if (!isset($options['attributes']['class'])) {
                $options['attributes']['class'] = array();
            }
            $string = is_string($options['attributes']['class']);
            if ($string) {
                $options['attributes']['class'] = explode(' ', $options['attributes']['class']);
            }
            $options['attributes']['class'][] = 'btn';
            $options['attributes']['class'][] = 'btn-xs';
            $options['attributes']['class'][] = 'btn-' . $class;
            if ($string) {
                $options['attributes']['class'] = implode(' ', $options['attributes']['class']);
            }
        }
        // Force HTML so we can render any icon that may have been added.
        $options['html'] = !empty($options['html']) || !empty($icon) ? TRUE : FALSE;
    }
    // Filter the title if the "html" is set, otherwise l() will automatically
    // sanitize using check_plain(), so no need to call that here.
    if (!empty($options['html'])) {
        $title = _bootstrap_filter_xss($title);
    }
    return $href ? l($icon . $title, $href, $options) : $icon . $title;
}
/**
 * Processes variables for the "bootstrap_modal" theme hook.
 *
 * See template for list of available variables.
 *
 * @see bootstrap-modal.tpl.php
 *
 * @ingroup theme_process
 */
function bootstrap_process_bootstrap_modal(&$variables)
{
    $variables['attributes'] = drupal_attributes($variables['attributes']);
    $variables['dialog_attributes'] = drupal_attributes($variables['dialog_attributes']);
    $variables['heading'] = _bootstrap_filter_xss(render($variables['heading']));
    $variables['body'] = render($variables['body']);
    $variables['footer'] = render($variables['footer']);
}
/**
 * Processes variables for the "block" theme hook.
 *
 * See template for list of available variables.
 *
 * @see block.tpl.php
 *
 * @ingroup theme_process
 */
function bootstrap_process_block(&$variables)
{
    // Drupal 7 should use a $title variable instead of $block->subject.
    // Don't override an existing "title" variable, some modules may already it.
    if (!isset($variables['title'])) {
        $variables['title'] = $variables['block']->subject;
    }
    $variables['title'] = _bootstrap_filter_xss($variables['title']);
}
/**
 * Processes variables for the "bootstrap_panel" theme hook.
 *
 * See template for list of available variables.
 *
 * @see bootstrap-panel.tpl.php
 *
 * @ingroup theme_process
 */
function bootstrap_process_bootstrap_panel(&$variables)
{
    $variables['attributes'] = drupal_attributes($variables['attributes']);
    if (!empty($variables['title'])) {
        $variables['title'] = _bootstrap_filter_xss(render($variables['title']));
    }
    if (!empty($variables['description'])) {
        $variables['description'] = _bootstrap_filter_xss(render($variables['description']));
    }
}
/**
 * Returns HTML for a button form element.
 *
 * @param array $variables
 *   An associative array containing:
 *   - element: An associative array containing the properties of the element.
 *     Properties used: #attributes, #button_type, #name, #value.
 *
 * @return string
 *   The constructed HTML.
 *
 * @see theme_button()
 *
 * @ingroup theme_functions
 */
function bootstrap_button($variables)
{
    $element = $variables['element'];
    // Allow button text to be appear hidden.
    // @see https://www.drupal.org/node/2327437
    $text = !empty($element['#hide_text']) ? '<span class="element-invisible">' . $element['#value'] . '</span>' : $element['#value'];
    // Add icons before or after the value.
    // @see https://www.drupal.org/node/2219965
    if (!empty($element['#icon'])) {
        if ($element['#icon_position'] === 'before') {
            $text = $element['#icon'] . ' ' . $text;
        } elseif ($element['#icon_position'] === 'after') {
            $text .= ' ' . $element['#icon'];
        }
    }
    // This line break adds inherent margin between multiple buttons.
    return '<button' . drupal_attributes($element['#attributes']) . '>' . _bootstrap_filter_xss($text) . "</button>\n";
}
/**
 * Processes variables for the "bootstrap_carousel" theme hook.
 *
 * See template for list of available variables.
 *
 * @see bootstrap-carousel.tpl.php
 *
 * @ingroup theme_process
 */
function bootstrap_process_bootstrap_carousel(&$variables)
{
    $variables['target'] = '#' . $variables['attributes']['id'];
    $variables['attributes'] = drupal_attributes($variables['attributes']);
    // Ensure the item arrays are constructed properly for the template.
    foreach ($variables['items'] as $delta => $item) {
        // Convert items that are string into the appropriate array structure.
        if (is_string($item)) {
            $variables['items'][$delta] = array('image' => $item);
        }
        // Populate defaults.
        $variables['items'][$delta] += array('title' => NULL, 'description' => NULL, 'url' => NULL);
        if (!empty($variables['items'][$delta]['title'])) {
            $variables['items'][$delta]['title'] = _bootstrap_filter_xss(render($item['title']));
        }
        if (!empty($variables['items'][$delta]['description'])) {
            $variables['items'][$delta]['description'] = _bootstrap_filter_xss(render($item['description']));
        }
    }
}
/**
 * Returns HTML for a single local task link.
 *
 * @param array $variables
 *   An associative array containing:
 *   - element: A render element containing:
 *     - #link: A menu link array with 'title', 'href', and 'localized_options'
 *       keys.
 *     - #active: A boolean indicating whether the local task is active.
 *
 * @return string
 *   The constructed HTML.
 *
 * @see theme_menu_local_task()
 *
 * @ingroup theme_functions
 */
function bootstrap_menu_local_task($variables)
{
    $link = $variables['element']['#link'];
    $options = isset($link['localized_options']) ? $link['localized_options'] : array();
    $title = $link['title'];
    $href = $link['href'];
    $attributes = array();
    // Add text to indicate active tab for non-visual users.
    if (!empty($variables['element']['#active'])) {
        $options['html'] = TRUE;
        $attributes['class'][] = 'active';
        $title = t('!local-task-title!active', array('!local-task-title' => $title, '!active' => '<span class="element-invisible">' . t('(active tab)') . '</span>'));
    }
    // Filter the title if the "html" is set, otherwise l() will automatically
    // sanitize using check_plain(), so no need to call that here.
    if (!empty($options['html'])) {
        $title = _bootstrap_filter_xss($title);
    }
    return '<li' . drupal_attributes($attributes) . '>' . l($title, $href, $options) . "</li>\n";
}
/**
 * Returns HTML for a list or nested list of items.
 *
 * - Uses an early D8 version of the theme function, which fixes bugs (and was
 *   refused for commit because it was "too late to change theme output)".
 * - Removes first/last, even/odd classes.
 * - Removes useless div.item-list wrapper, allows optional #wrapper_attributes.
 * - Removes hard-coded #title as <h3>, introduce support for #title as an array
 *   containing, text, tag and optional attributes.
 *
 * @param array $variables
 *   An associative array containing:
 *   - items: An array of items to be displayed in the list. If an item is a
 *     string, then it is used as is. If an item is an array, then the "data"
 *     element of the array is used as the contents of the list item. If an item
 *     is an array with a "children" element, those children are displayed in a
 *     nested list. All other elements are treated as attributes of the list
 *     item element.
 *   - title: The title of the list.
 *   - type: The type of list to return (e.g. "ul", "ol").
 *   - attributes: The attributes applied to the list element.
 *
 * @return string
 *   The constructed HTML.
 *
 * @see theme_item_list()
 *
 * @ingroup theme_functions
 */
function bootstrap_item_list($variables)
{
    $items = $variables['items'];
    $title = $variables['title'];
    $type = $variables['type'];
    $list_attributes = $variables['attributes'];
    // Drupal core only supports #title as a string. This implementation supports
    // heading level, and attributes as well.
    $heading = '';
    if (!empty($title)) {
        // If it's a string, normalize into an array.
        if (is_string($title)) {
            $title = array('text' => $title);
        }
        // Set defaults.
        $title += array('level' => 'h3', 'attributes' => array());
        // Heading outputs only when it has text.
        if (!empty($title['text'])) {
            $heading .= '<' . $title['level'] . drupal_attributes($title['attributes']) . '>';
            $heading .= empty($title['html']) ? check_plain($title['text']) : _bootstrap_filter_xss($title['text']);
            $heading .= '</' . $title['level'] . '>';
        }
    }
    $output = '';
    if ($items) {
        $output .= '<' . $type . drupal_attributes($list_attributes) . '>';
        foreach ($items as $key => $item) {
            $attributes = array();
            if (is_array($item)) {
                $value = '';
                if (isset($item['data'])) {
                    // Allow data to be renderable.
                    if (is_array($item['data']) && (!empty($item['data']['#type']) || !empty($item['data']['#theme']))) {
                        $value .= drupal_render($item['data']);
                    } else {
                        $value .= $item['data'];
                    }
                }
                $attributes = array_diff_key($item, array('data' => 0, 'children' => 0));
                // Append nested child list, if any.
                if (isset($item['children'])) {
                    // HTML attributes for the outer list are defined in the 'attributes'
                    // theme variable, but not inherited by children. For nested lists,
                    // all non-numeric keys in 'children' are used as list attributes.
                    $child_list_attributes = array();
                    foreach ($item['children'] as $child_key => $child_item) {
                        if (is_string($child_key)) {
                            $child_list_attributes[$child_key] = $child_item;
                            unset($item['children'][$child_key]);
                        }
                    }
                    $value .= theme('item_list', array('items' => $item['children'], 'type' => $type, 'attributes' => $child_list_attributes));
                }
            } else {
                $value = $item;
            }
            $output .= '<li' . drupal_attributes($attributes) . '>' . $value . "</li>\n";
        }
        $output .= "</{$type}>";
    }
    // Output the list and title only if there are any list items.
    if (!empty($output)) {
        $output = $heading . $output;
    }
    return $output;
}
/**
 * Processes variables for the "progress_bar" theme hook.
 *
 * See template for list of available variables.
 *
 * @see progress-bar.tpl.php
 *
 * @ingroup theme_process
 */
function bootstrap_process_progress_bar(&$variables)
{
    $variables['percent'] = check_plain($variables['percent']);
    $variables['message'] = _bootstrap_filter_xss($variables['message']);
}