/** * Global #process callback for form elements. * * @param array $element * The element render array. * @param \Drupal\Core\Form\FormStateInterface $form_state * The current state of the form. * @param array $complete_form * The complete form structure. * * @return array * The altered element array. * * @see \Drupal\materialize\Plugin\Alter\ElementInfo::alter */ public static function process(array $element, FormStateInterface $form_state, array &$complete_form) { if (!empty($element['#materialize_ignore_process'])) { return $element; } static $theme; if (!isset($theme)) { $theme = Materialize::getTheme(); } $e = Element::create($element, $form_state); // Process AJAX. if ($e->getProperty('ajax') && !$e->isButton() || $e->getProperty('autocomplete_route_name')) { static::processAjax($e, $form_state, $complete_form); } // Add "form-inline" class. if ($e->hasClass('container-inline')) { $e->replaceClass('container-inline', 'form-inline'); } if ($e->isType(['color', 'date', 'number', 'range', 'tel', 'weight'])) { $e->addClass('form-inline', 'wrapper_attributes'); } // Check for errors and set the "has_error" property flag. $errors = $e->getError(); $e->setProperty('errors', $errors); if (isset($errors) || $e->getProperty('required') && $theme->getSetting('forms_required_has_error')) { $e->setProperty('has_error', TRUE); } // Process input groups. if ($e->getProperty('input') && ($e->getProperty('input_group') || $e->getProperty('input_group_button'))) { static::processInputGroups($e, $form_state, $complete_form); } return $element; }
/** * Extracts the hook name from a function name. * * @param string $string * The function name to extract the hook name from. * @param string $suffix * A suffix hook ending (like "alter") to also remove. * @param string $prefix * A prefix hook beginning (like "form") to also remove. * * @return string * The extracted hook name. */ public static function extractHook($string, $suffix = NULL, $prefix = NULL) { $regex = '^(' . implode('|', array_keys(Materialize::getTheme()->getAncestry())) . ')'; $regex .= $prefix ? '_' . $prefix : ''; $regex .= $suffix ? '_|_' . $suffix . '$' : ''; return preg_replace("/{$regex}/", '', $string); }
/** * {@inheritdoc} */ public function __construct(array $configuration, $plugin_id, $plugin_definition) { if (!isset($configuration['theme'])) { $configuration['theme'] = Materialize::getTheme(); } $this->theme = $configuration['theme']; parent::__construct($configuration, $plugin_id, $plugin_definition); }
/** * Retrieves the currently selected theme on the settings form. * * @param array $form * Nested array of form elements that comprise the form. * @param \Drupal\Core\Form\FormStateInterface $form_state * The current state of the form. * * @return \Drupal\materialize\Theme|FALSE * The currently selected theme object or FALSE if not a Materialize theme. */ public static function getTheme(array &$form, FormStateInterface $form_state) { $build_info = $form_state->getBuildInfo(); $theme = isset($build_info['args'][0]) ? Materialize::getTheme($build_info['args'][0]) : FALSE; // Do not continue if the theme is not Materialize specific. if (!$theme || !$theme->subthemeOf('materialize')) { unset($form['#submit'][0]); unset($form['#validate'][0]); } return $theme; }
/** * {@inheritdoc} */ public function __construct(array $configuration, $plugin_id, $plugin_definition) { // This is technically a plugin constructor, but because we wish to use the // protected methods of the Registry class, we must extend from it. Thus, // to properly construct the extended Registry object, we must pass the // arguments it would normally get from the service container to "fake" it. if (!isset($configuration['theme'])) { $configuration['theme'] = Materialize::getTheme(); } $this->currentTheme = $configuration['theme']; parent::__construct(\Drupal::service('app.root'), \Drupal::service('cache.default'), \Drupal::service('lock'), \Drupal::service('module_handler'), \Drupal::service('theme_handler'), \Drupal::service('theme.initialization'), $this->currentTheme->getName()); $this->setThemeManager(\Drupal::service('theme.manager')); $this->init(); }
/** * Retrieves the full base/sub-theme ancestry of a theme. * * @param bool $reverse * Whether or not to return the array of themes in reverse order, where the * active theme is the first entry. * * @return \Drupal\bootstrap\Theme[] * An associative array of \Drupal\bootstrap objects (theme), keyed * by machine name. */ public function getAncestry($reverse = FALSE) { $ancestry = $this->themeHandler->getBaseThemes($this->themes, $this->getName()); foreach (array_keys($ancestry) as $name) { $ancestry[$name] = Materialize::getTheme($name, $this->themeHandler); } $ancestry[$this->getName()] = $this; return $reverse ? array_reverse($ancestry) : $ancestry; }
/** * 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; }