/**
  * Manages theme alter hooks as classes and allows sub-themes to sub-class.
  *
  * @param string $function
  *   The procedural function name of the alter (e.g. __FUNCTION__).
  * @param mixed $data
  *   The variable that was passed to the hook_TYPE_alter() implementation to
  *   be altered. The type of this variable depends on the value of the $type
  *   argument. For example, when altering a 'form', $data will be a structured
  *   array. When altering a 'profile', $data will be an object.
  * @param mixed $context1
  *   (optional) An additional variable that is passed by reference.
  * @param mixed $context2
  *   (optional) An additional variable that is passed by reference. If more
  *   context needs to be provided to implementations, then this should be an
  *   associative array as described above.
  */
 public static function alter($function, &$data, &$context1 = NULL, &$context2 = NULL)
 {
     static $theme;
     if (!isset($theme)) {
         $theme = self::getTheme();
     }
     // Immediately return if the active theme is not Bootstrap based.
     if (!$theme->subthemeOf('materialize')) {
         return;
     }
     // Extract the alter hook name.
     $hook = Unicode::extractHook($function, 'alter');
     // Handle form alters separately.
     if (strpos($hook, 'form') === 0) {
         $form_id = $context2;
         if (!$form_id) {
             $form_id = Unicode::extractHook($function, 'alter', 'form');
         }
         // Due to a core bug that affects admin themes, we should not double
         // process the "system_theme_settings" form twice in the global
         // hook_form_alter() invocation.
         // @see https://drupal.org/node/943212
         if ($context2 === 'system_theme_settings') {
             return;
         }
         // Retrieve a list of form definitions.
         $form_manager = new FormManager($theme);
         /** @var \Drupal\bootstrap\Plugin\Form\FormInterface $form */
         if ($form_manager->hasDefinition($form_id) && ($form = $form_manager->createInstance($form_id, ['theme' => $theme]))) {
             $data['#submit'][] = [get_class($form), 'submitForm'];
             $data['#validate'][] = [get_class($form), 'validateForm'];
             $form->alterForm($data, $context1, $context2);
         }
     } else {
         // Retrieve a list of alter definitions.
         $alter_manager = new AlterManager($theme);
         /** @var \Drupal\bootstrap\Plugin\Alter\AlterInterface $class */
         if ($alter_manager->hasDefinition($hook) && ($class = $alter_manager->createInstance($hook, ['theme' => $theme]))) {
             $class->alter($data, $context1, $context2);
         }
     }
 }
예제 #2
0
 /**
  * Converts an element description into a tooltip based on certain criteria.
  *
  * @param array|\Drupal\materialize\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 = Materialize::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;
 }