bootstrap_theme_toggler-2.0.0/src/Plugin/Block/themeToggler.php

src/Plugin/Block/themeToggler.php
<?php

namespace Drupal\bootstrap_theme_toggler\Plugin\Block;

use Drupal\Core\Block\BlockBase;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Render\Markup;

/**
 * Provides a 'Theme Toggler' Block.
 *
 * @Block(
 *   id = "theme_toggler",
 *   admin_label = @Translation("Theme Toggler"),
 *   category = @Translation("Theme Toggler Block"),
 * )
 * 
 * When place, the machine name of the block instance will be enforced to be
 * the default name provided by Drupal, which should be the Block 'id' above,
 * without the underscore, 'themetoggler', prefixed by the default theme name
 * resulting in a machine name of 'loaded_default_theme_themetoggler'.
 * This is used to enforce only 1 instance of this block is placed on the site.
 */
class ThemeToggler extends BlockBase {

  /**
   * {@inheritdoc}
   */
  public function build() {

    $config = $this->configuration;

    if (!$config['custom_only']) {
      // array of default bootstrap theme modes, use all or none.
      $bm = array("auto"=>"auto", "light"=>"light", "dark"=>"dark");
    } else {
      $bm = array();
    }
    // Need to gaurd against null, color modes, may not exist.
    if (!empty($config['color_modes'])) {
      if (!empty($bm)) {
        $themeModes = array_merge($bm, $config['color_modes']);
      } else {
        $themeModes = $config['color_modes'];
      }
    } else {
      $themeModes = $bm;
    }

    return [
      '#theme' => 'block__toggler',
      '#attached' => [
        'library' => ['bootstrap_theme_toggler/theme-toggler'],
      ],
      '#toggler_label' => $config['toggler_label'],
      '#show_toggler_label' => $config['show_toggler_label'],
      '#show_option_labels' => $config['show_option_labels'],
      '#show_icons' => $config['show_icons'],
      '#show_checkmark' => $config['show_checkmark'],
      '#theme_modes' => $themeModes,
      // '#custom_only' => $config['custom_only'],
    ];

  } // END of build()


  /**
   * Returns generic default configuration for block plugins.
   *
   * @return array
   *   An associative array with the default configuration.
   */
  protected function baseConfigurationDefaults() {
    return [
      'label' => 'Bootstrap Theme Toggler',
      'label_display' => 0,
      'provider' => $this->pluginDefinition['provider'],
      //   '#default_value' => false,
      //   '#return_value' => false,
    ];
  }


  /**
   * {@inheritdoc}
   */
  public function blockForm($form, FormStateInterface $form_state) {

    $config = $this->configuration;

    // Message template to add a close button to drupal messenger messages.
    // The close button requires javascript `js/messenger-close.js`
    $message_html = '
      <div style="display: flex; flex-direction: row; align-items: center">
      <div id="messenger-close" style="width:2em; text-align: center">
        <button style="background-color:yellow; border:0; border-radius:1em; cursor:pointer" >
          X
        </button>
      </div>
        <div style="align-self: stretch; background-color: blue; width:5px">
        </div>
        <div style="margin:10px">
          message
        </div>
      </div>
    ';

    $form['toggler_label'] = [
      '#type' => 'textfield',
      '#title' => $this->t('Toggler Label'),
      '#description' => $this->t('Text to display on the toggler dropdown button.'),
      '#default_value' => $config['toggler_label'] ?? 'Theme',
    ];
    $form['show_toggler_label'] = [
      '#type' => 'checkbox',
      '#title' => $this->t('Show toggler label'),
      // '#description' => $this->t('Check to make button label visible, on Toggler.'),
      '#default_value' => $config['show_toggler_label'] ?? true,
    ];
    $form['show_option_labels'] = [
      '#type' => 'checkbox',
      '#title' => $this->t('Show theme mode option labels in dropdown list.'),
      // '#description' => $this->t('Check to make drop-down option labels visible, on Toggler.'),
      '#default_value' => $config['show_option_labels'] ?? true,
    ];
    $form['show_icons'] = [
      '#type' => 'checkbox',
      '#title' => $this->t('Show toggler color mode icons'),
      '#description' => $this->t("To change icons being displayed, edit/replace the appropriate svg with the name of the theme mode to update. The svg element inside must be defined by a &lt;sybmol&gt; element, with an id matching the theme name. The filename should be the theme name prefixed by 'icon_'. <br>A replacement icon for the 'light' theme mode should have the tag, <code><xmp><symbol id='light'><path>...</path></symbol></xmp></code>and have the filename and location of <b>`bootstrap_theme_toggler/svg/icon_light.svg`</b>."),
      '#default_value' => $config['show_icons'] ?? true,
    ];
    $form['show_checkmark'] = [
      '#type' => 'checkbox',
      '#title' => $this->t('Show a checkmark next to active theme'),
      // '#description' => $this->t('Check to show a checkmark next to active theme.'),
      '#default_value' => $config['show_checkmark'] ?? true,
    ];

    // Get the the loaded 'default' theme, not the 'active' theme.
    $themeRoot = \Drupal::config('system.theme')->getOriginal('default');
    // To use custom color modes a theme must be compatible.
    // By default only Bootstrap Bario SASS themes are assumed compatible.           
    // Existence of `gulpfile.js` is taken as indication of Barrio SASS theme.
    $themeGulpfileExists = file_exists(\Drupal::service('extension.list.theme')->getPath($themeRoot).'/gulpfile.js');

    // Get the global Bootstrap Theme Toggler settings
    $globalConfig = \Drupal::service('config.factory')->getEditable('bootstrap_theme_toggler.settings');

    // A theme can also be manually indicatad as compatible with color modes
    // by checking the `add custom color modes` global configuration setting.
    // Only load and show custom color modes if theme is indicated compatible.
    if ($themeGulpfileExists || $globalConfig->get('add_custom_color_modes')) {

      // Check if alternate color mode path has been set in global config.
      $colorModeDefs = $globalConfig->get('color_mode_sass_directory');
      if ($colorModeDefs) {
        // Notify the user that a custom color mode path has been set.
        $messageText = 'The default custom color mode folder has been changed to: <b>'.
            $colorModeDefs .'</b><br>To reset to default, or edit, go to <a href="'.
            \Drupal::request()->getSchemeAndHttpHost().
            '/admin/config/bootstrap-theme-toggler">Bootstrap Theme Toggler Global config</a>.';
        $message = [
          '#type' => 'markup',
          '#attached' => [
            'library' => array('bootstrap_theme_toggler/messenger-close'),
          ],
          '#markup' => Markup::create(str_replace('message', $messageText, $message_html)),
        ];
        \Drupal::messenger()->addMessage($message, 'toggler');
      } else {
        // If alternate path has not been set, use module's scss folder.
        $colorModeDefs = \Drupal::service('extension.list.module')->getPath('bootstrap_theme_toggler').'/scss/';
      }

      $prefix = '_';
      $result = array();
      $defaultValues = array();

      // Look for color mode scss files, indicated by a leading '_',
      // inside specified custom color modes folder.
      $handle = @opendir($colorModeDefs);
      if (!empty($handle)) {
        while ($entry = @readdir($handle)) {
          // If item is a file and has matching prefix, process as a theme mode.
          if(is_file($colorModeDefs.$entry) && (mb_substr($entry, 0, 1) == $prefix)) {
            $result[str_replace($prefix, '', pathinfo($entry, PATHINFO_FILENAME))] = str_replace($prefix, '', pathinfo($entry, PATHINFO_FILENAME));
            // Building array of values only, for use in setting default_value.
            $defaultValues[] = str_replace($prefix, '', pathinfo($entry, PATHINFO_FILENAME));
          }
        }
        closedir($handle);
      }

    } // END of if SASS custom color mode exist

    // Creates checkbox to enable/disable each custom scss theme modes found.
    if (!empty($result)){
      $config = $this->configuration['color_modes'] ?? ($defaultValues ?? null);
      // For checkboxes, the array keys are used to set the checkbox values
      // and the array values are used to set the checkbox labels.
      $form['color_modes'] = array(
        '#type' => 'checkboxes',
        '#title' => $this->t('Custom Theme Modes Available'),
        '#options' => $result,
        '#description' => $this->t('Select custom theme modes to include on toggler toggler.'),
        '#default_value' => $config,
      );
      $form['custom_only'] = [
        '#type' => 'checkbox',
        '#title' => $this->t('Use only custom theme modes'),
        '#description' => $this->t("Checking this will disable 'light', 'dark' and 'auto' themes."),
        '#default_value' => $this->configuration['custom_only'] ?? false,
      ];
    } else {
      // Notify users that custom color modes don't exist, or are not enabled
      $form['text_no_colors'] = array(
        '#type' => 'item',
        '#title' => $this->t('No Custom Theme Modes Found'),
        '#description' => $this->t("
          Custom Theme Modes are only assumed compatible for Bootstrap Barrio SASS based themes.<br>
          Theme's can also be manually indicated as compatible in the Theme Toggler global settings.
        "),
      );
    }

    return $form;
  } // END blockForm


  /**
   * {@inheritdoc}
   */
  public function blockValidate ($form, FormStateInterface $form_state) {
    
    // Check that the machine name matches the required default name.
    // Used to prevent more than one instance of this block being placed.

    // Get default theme name used to determine the block's machine name.
    $defaultTheme = \Drupal::config('system.theme')->getOriginal('default');
    // Get the actual machine name set for current block instance.
    $machine_name = $form_state->get('machine_name.initial_values');
    $defaultName = $machine_name['id'] == $defaultTheme.'_themetoggler';

    if (!$defaultName) {
      $form_state->setErrorByName('machine_name', $this->
          t("Another instance of this block already exists, or the default machine name has been changed. <br> Make sure toggler machine name is 'DEFAULT_THEME_themetoggler', and that it has not already been placed into your site."));
    }
    $values = $form_state->getValues();
    if (!empty($values['custom_only'])) {
      if (empty(array_filter( $values['color_modes'] ?? [0] ))){
        $form_state->setErrorByName('color_modes', $this->
          t("Cannot select 'Custom Only' and have no custom themes enabled."));
      }
    }
  }


  /**
   * {@inheritdoc}
   */
  public function blockSubmit($form, FormStateInterface $form_state) {

    $values = $form_state->getValues();
    $this->configuration['toggler_label'] = $values['toggler_label'];
    $this->configuration['show_toggler_label'] = $values['show_toggler_label'];
    $this->configuration['show_option_labels'] = $values['show_option_labels'];
    $this->configuration['show_icons'] = $values['show_icons'];
    $this->configuration['show_checkmark'] = $values['show_checkmark'];
    $this->configuration['custom_only'] = $values['custom_only'] ?? null;
    $this->configuration['color_modes'] = $values['color_modes'] ?? false;
    
    // Need to remove messages set by config form.
    // Even if closed by user, they will re-appear if not removed.
    \Drupal::messenger()->deleteByType('toggler');

  }

} // END ThemeToggler class

Главная | Обратная связь

drupal hosting | друпал хостинг | it patrol .inc