/** * Preprocess links in the variables array to convert them from dropbuttons. * * @param \Drupal\bootstrap\Utility\Variables $variables * A variables object. */ protected function preprocessLinks(Variables $variables) { // Convert "dropbutton" theme suggestion variables. if (Unicode::strpos($variables->theme_hook_original, 'links__dropbutton') !== FALSE && !empty($variables->links)) { $operations = !!Unicode::strpos($variables->theme_hook_original, 'operations'); // Normal dropbutton links are not actually render arrays, convert them. foreach ($variables->links as &$link) { if (isset($link['title']) && $link['url']) { $link = ['#type' => 'link', '#title' => $link['title'], '#url' => $link['url']]; } } // Pop off the first link as the "toggle". $variables->toggle = array_shift($variables->links); $toggle = Element::create($variables->toggle); // Convert any toggle links to a proper button. if ($toggle->isType('link')) { $toggle->exchangeArray(['#type' => 'button', '#value' => $toggle->getProperty('title'), '#attributes' => ['data-url' => $toggle->getProperty('url')->toString()]]); if ($operations) { $toggle->setButtonSize('btn-xs'); } } else { $toggle->unsetProperty('dropbutton'); } $variables->items = array_values($variables->links); $variables->split = TRUE; unset($variables->links); } }
/** * {@inheritdoc} */ public function alter(&$suggestions, &$variables = NULL, &$hook = NULL) { switch ($hook) { case 'links': if (Unicode::strpos($variables['theme_hook_original'], 'links__dropbutton') !== FALSE) { // Handle dropbutton "subtypes". // @see \Drupal\bootstrap\Plugin\Prerender\Dropbutton::preRenderElement() if ($suggestion = Unicode::substr($variables['theme_hook_original'], 17)) { $suggestions[] = 'bootstrap_dropdown' . $suggestion; } $suggestions[] = 'bootstrap_dropdown'; } break; case 'fieldset': case 'details': $suggestions[] = 'bootstrap_panel'; break; case 'input': $element = Element::create($variables['element']); if ($element->isButton()) { if ($element->getProperty('dropbutton')) { $suggestions[] = 'input__button__dropdown'; } else { $suggestions[] = $element->getProperty('split') ? 'input__button__split' : 'input__button'; } } elseif (!$element->isType(['checkbox', 'hidden', 'radio'])) { $suggestions[] = 'input__form_control'; } break; } }
/** * Determines if a string of text is considered "simple". * * @param string $string * The string of text to check "simple" criteria on. * @param int|FALSE $length * The length of characters used to determine whether or not $string is * considered "simple". Set explicitly to FALSE to disable this criteria. * @param array|FALSE $allowed_tags * An array of allowed tag elements. Set explicitly to FALSE to disable this * criteria. * @param bool $html * A variable, passed by reference, that indicates whether or not the * string contains HTML. * * @return bool * Returns TRUE if the $string is considered "simple", FALSE otherwise. * * @deprecated Will be removed in a future release. * * @code * // Before. * $simple = _bootstrap_is_simple_string($string, $length, $allowed_tags, $html); * * // After. * use Drupal\bootstrap\Utility\Unicode; * $simple = Unicode::isSimple($string, $length, $allowed_tags, $html); * @endcode * * @see \Drupal\bootstrap\Utility\Unicode::isSimple() */ function _bootstrap_is_simple_string($string, $length = 250, $allowed_tags = NULL, &$html = FALSE) { Bootstrap::deprecated(); return Unicode::isSimple($string, $length, $allowed_tags, $html); }
/** * Converts an element description into a tooltip based on certain criteria. * * @param array|\Drupal\bootstrap\Utility\Element|NULL $target_element * The target element render array the tooltip is to be attached to, passed * by reference or an existing Element object. If not set, it will default * this Element instance. * @param bool $input_only * Toggle determining whether or not to only convert input elements. * @param int $length * The length of characters to determine if description is "simple". * * @return $this */ public function smartDescription(&$target_element = NULL, $input_only = TRUE, $length = NULL) { static $theme; if (!isset($theme)) { $theme = Bootstrap::getTheme(); } // Determine if tooltips are enabled. static $enabled; if (!isset($enabled)) { $enabled = $theme->getSetting('tooltip_enabled') && $theme->getSetting('forms_smart_descriptions'); } // Immediately return if tooltip descriptions are not enabled. if (!$enabled) { return $this; } // Allow a different element to attach the tooltip. /** @var Element $target */ if (is_object($target_element) && $target_element instanceof self) { $target = $target_element; } elseif (isset($target_element) && is_array($target_element)) { $target = new self($target_element, $this->formState); } else { $target = $this; } // Retrieve the length limit for smart descriptions. if (!isset($length)) { // Disable length checking by setting it to FALSE if empty. $length = (int) $theme->getSetting('forms_smart_descriptions_limit') ?: FALSE; } // Retrieve the allowed tags for smart descriptions. This is primarily used // for display purposes only (i.e. non-UI/UX related elements that wouldn't // require a user to "click", like a link). Disable length checking by // setting it to FALSE if empty. static $allowed_tags; if (!isset($allowed_tags)) { $allowed_tags = array_filter(array_unique(array_map('trim', explode(',', $theme->getSetting('forms_smart_descriptions_allowed_tags') . '')))) ?: FALSE; } // Return if element or target shouldn't have "simple" tooltip descriptions. $html = FALSE; if ($input_only && !$target->hasProperty('input') || !$this->getProperty('smart_description', TRUE) || !$target->getProperty('smart_description', TRUE) || !$this->hasProperty('description') || $target->hasAttribute('data-toggle') || !Unicode::isSimple($this->getProperty('description'), $length, $allowed_tags, $html)) { return $this; } // Default attributes type. $type = DrupalAttributes::ATTRIBUTES; // Use #label_attributes for 'checkbox' and 'radio' elements. if ($this->isType(['checkbox', 'radio'])) { $type = DrupalAttributes::LABEL; } elseif ($this->isType(['checkboxes', 'radios'])) { $type = DrupalAttributes::WRAPPER; } // Retrieve the proper attributes array. $attributes = $target->getAttributes($type); // Set the tooltip attributes. $attributes['title'] = $allowed_tags !== FALSE ? Xss::filter((string) $this->getProperty('description'), $allowed_tags) : $this->getProperty('description'); $attributes['data-toggle'] = 'tooltip'; if ($html || $allowed_tags === FALSE) { $attributes['data-html'] = 'true'; } // Remove the element description so it isn't (re-)rendered later. $this->unsetProperty('description'); return $this; }
/** * Matches a Bootstrap Glyphicon based on a string value. * * @param string $string * The string to match classes against. * @param array $default * The default render array to return if no match is found. * * @return string * The Bootstrap icon matched against the value of $haystack or $default if * no match could be made. */ public static function glyphiconFromString($string, $default = []) { static $lang; if (!isset($lang)) { $lang = \Drupal::languageManager()->getCurrentLanguage()->getId(); } $theme = Bootstrap::getTheme(); $texts = $theme->getCache('glyphiconFromString', [$lang]); $string = (string) $string; if ($texts->isEmpty()) { $data = ['matches' => [], 'contains' => [t('Manage')->render() => 'cog', t('Configure')->render() => 'cog', t('Settings')->render() => 'cog', t('Download')->render() => 'download', t('Export')->render() => 'export', t('Filter')->render() => 'filter', t('Import')->render() => 'import', t('Save')->render() => 'ok', t('Update')->render() => 'ok', t('Edit')->render() => 'pencil', t('Uninstall')->render() => 'trash', t('Install')->render() => 'plus', t('Write')->render() => 'plus', t('Cancel')->render() => 'remove', t('Delete')->render() => 'trash', t('Remove')->render() => 'trash', t('Search')->render() => 'search', t('Upload')->render() => 'upload', t('Preview')->render() => 'eye-open']]; // Allow sub-themes to alter this array of patterns. /** @var \Drupal\Core\Theme\ThemeManager $theme_manager */ $theme_manager = \Drupal::service('theme.manager'); $theme_manager->alter('bootstrap_iconize_text', $data); $texts->setMultiple($data); } // Iterate over the array. foreach ($texts as $pattern => $strings) { foreach ($strings as $value => $icon) { switch ($pattern) { case 'matches': if ($string === $value) { return self::glyphicon($icon, $default); } break; case 'contains': if (strpos(Unicode::strtolower($string), Unicode::strtolower($value)) !== FALSE) { return self::glyphicon($icon, $default); } break; } } } // Return a default icon if nothing was matched. return $default; }