You are here

public function ThemeSettingsForm::buildForm in Drupal 8

Same name and namespace in other branches
  1. 9 core/modules/system/src/Form/ThemeSettingsForm.php \Drupal\system\Form\ThemeSettingsForm::buildForm()
  2. 10 core/modules/system/src/Form/ThemeSettingsForm.php \Drupal\system\Form\ThemeSettingsForm::buildForm()

Parameters

string $theme: The theme name.

Overrides ConfigFormBase::buildForm

File

core/modules/system/src/Form/ThemeSettingsForm.php, line 133

Class

ThemeSettingsForm
Displays theme configuration for entire site and individual themes.

Namespace

Drupal\system\Form

Code

public function buildForm(array $form, FormStateInterface $form_state, $theme = '') {
  $form = parent::buildForm($form, $form_state);
  $themes = $this->themeHandler
    ->listInfo();

  // Default settings are defined in theme_get_setting() in includes/theme.inc
  if ($theme) {
    if (!$this->themeHandler
      ->hasUi($theme)) {
      throw new NotFoundHttpException();
    }
    $var = 'theme_' . $theme . '_settings';
    $config_key = $theme . '.settings';
    $themes = $this->themeHandler
      ->listInfo();
    $features = $themes[$theme]->info['features'];
  }
  else {
    $var = 'theme_settings';
    $config_key = 'system.theme.global';
  }

  // @todo this is pretty meaningless since we're using theme_get_settings
  //   which means overrides can bleed into active config here. Will be fixed
  //   by https://www.drupal.org/node/2402467.
  $this->editableConfig = [
    $config_key,
  ];
  $form['var'] = [
    '#type' => 'hidden',
    '#value' => $var,
  ];
  $form['config_key'] = [
    '#type' => 'hidden',
    '#value' => $config_key,
  ];

  // Toggle settings
  $toggles = [
    'node_user_picture' => t('User pictures in posts'),
    'comment_user_picture' => t('User pictures in comments'),
    'comment_user_verification' => t('User verification status in comments'),
    'favicon' => t('Shortcut icon'),
  ];

  // Some features are not always available
  $disabled = [];
  if (!user_picture_enabled()) {
    $disabled['toggle_node_user_picture'] = TRUE;
    $disabled['toggle_comment_user_picture'] = TRUE;
  }
  if (!$this->moduleHandler
    ->moduleExists('comment')) {
    $disabled['toggle_comment_user_picture'] = TRUE;
    $disabled['toggle_comment_user_verification'] = TRUE;
  }
  $form['theme_settings'] = [
    '#type' => 'details',
    '#title' => t('Page element display'),
    '#open' => TRUE,
  ];
  foreach ($toggles as $name => $title) {
    if (!$theme || in_array($name, $features)) {
      $form['theme_settings']['toggle_' . $name] = [
        '#type' => 'checkbox',
        '#title' => $title,
        '#default_value' => theme_get_setting('features.' . $name, $theme),
      ];

      // Disable checkboxes for features not supported in the current configuration.
      if (isset($disabled['toggle_' . $name])) {
        $form['theme_settings']['toggle_' . $name]['#disabled'] = TRUE;
      }
    }
  }
  if (!Element::children($form['theme_settings'])) {

    // If there is no element in the theme settings details then do not show
    // it -- but keep it in the form if another module wants to alter.
    $form['theme_settings']['#access'] = FALSE;
  }

  // Logo settings, only available when file.module is enabled.
  if ((!$theme || in_array('logo', $features)) && $this->moduleHandler
    ->moduleExists('file')) {
    $form['logo'] = [
      '#type' => 'details',
      '#title' => t('Logo image'),
      '#open' => TRUE,
    ];
    $form['logo']['default_logo'] = [
      '#type' => 'checkbox',
      '#title' => t('Use the logo supplied by the theme'),
      '#default_value' => theme_get_setting('logo.use_default', $theme),
      '#tree' => FALSE,
    ];
    $form['logo']['settings'] = [
      '#type' => 'container',
      '#states' => [
        // Hide the logo settings when using the default logo.
        'invisible' => [
          'input[name="default_logo"]' => [
            'checked' => TRUE,
          ],
        ],
      ],
    ];
    $form['logo']['settings']['logo_path'] = [
      '#type' => 'textfield',
      '#title' => t('Path to custom logo'),
      '#default_value' => theme_get_setting('logo.path', $theme),
    ];
    $form['logo']['settings']['logo_upload'] = [
      '#type' => 'file',
      '#title' => t('Upload logo image'),
      '#maxlength' => 40,
      '#description' => t("If you don't have direct file access to the server, use this field to upload your logo."),
      '#upload_validators' => [
        'file_validate_is_image' => [],
      ],
    ];
  }
  if ((!$theme || in_array('favicon', $features)) && $this->moduleHandler
    ->moduleExists('file')) {
    $form['favicon'] = [
      '#type' => 'details',
      '#title' => t('Favicon'),
      '#open' => TRUE,
      '#description' => t("Your shortcut icon, or favicon, is displayed in the address bar and bookmarks of most browsers."),
      '#states' => [
        // Hide the shortcut icon settings fieldset when shortcut icon display
        // is disabled.
        'invisible' => [
          'input[name="toggle_favicon"]' => [
            'checked' => FALSE,
          ],
        ],
      ],
    ];
    $form['favicon']['default_favicon'] = [
      '#type' => 'checkbox',
      '#title' => t('Use the favicon supplied by the theme'),
      '#default_value' => theme_get_setting('favicon.use_default', $theme),
    ];
    $form['favicon']['settings'] = [
      '#type' => 'container',
      '#states' => [
        // Hide the favicon settings when using the default favicon.
        'invisible' => [
          'input[name="default_favicon"]' => [
            'checked' => TRUE,
          ],
        ],
      ],
    ];
    $form['favicon']['settings']['favicon_path'] = [
      '#type' => 'textfield',
      '#title' => t('Path to custom icon'),
      '#default_value' => theme_get_setting('favicon.path', $theme),
    ];
    $form['favicon']['settings']['favicon_upload'] = [
      '#type' => 'file',
      '#title' => t('Upload favicon image'),
      '#description' => t("If you don't have direct file access to the server, use this field to upload your shortcut icon."),
      '#upload_validators' => [
        'file_validate_extensions' => [
          'ico png gif jpg jpeg apng svg',
        ],
      ],
    ];
  }

  // Inject human-friendly values and form element descriptions for logo and
  // favicon.
  foreach ([
    'logo' => 'logo.svg',
    'favicon' => 'favicon.ico',
  ] as $type => $default) {
    if (isset($form[$type]['settings'][$type . '_path'])) {
      $element =& $form[$type]['settings'][$type . '_path'];

      // If path is a public:// URI, display the path relative to the files
      // directory; stream wrappers are not end-user friendly.
      $original_path = $element['#default_value'];
      $friendly_path = NULL;
      if (StreamWrapperManager::getScheme($original_path) == 'public') {
        $friendly_path = StreamWrapperManager::getTarget($original_path);
        $element['#default_value'] = $friendly_path;
      }

      // Prepare local file path for description.
      if ($original_path && isset($friendly_path)) {
        $local_file = strtr($original_path, [
          'public:/' => PublicStream::basePath(),
        ]);
      }
      elseif ($theme) {
        $local_file = drupal_get_path('theme', $theme) . '/' . $default;
      }
      else {
        $local_file = $this->themeManager
          ->getActiveTheme()
          ->getPath() . '/' . $default;
      }
      $element['#description'] = t('Examples: <code>@implicit-public-file</code> (for a file in the public filesystem), <code>@explicit-file</code>, or <code>@local-file</code>.', [
        '@implicit-public-file' => isset($friendly_path) ? $friendly_path : $default,
        '@explicit-file' => StreamWrapperManager::getScheme($original_path) !== FALSE ? $original_path : 'public://' . $default,
        '@local-file' => $local_file,
      ]);
    }
  }
  if ($theme) {

    // Call engine-specific settings.
    $function = $themes[$theme]->prefix . '_engine_settings';
    if (function_exists($function)) {
      $form['engine_specific'] = [
        '#type' => 'details',
        '#title' => t('Theme-engine-specific settings'),
        '#open' => TRUE,
        '#description' => t('These settings only exist for the themes based on the %engine theme engine.', [
          '%engine' => $themes[$theme]->prefix,
        ]),
      ];
      $function($form, $form_state);
    }

    // Create a list which includes the current theme and all its base themes.
    if (isset($themes[$theme]->base_themes)) {
      $theme_keys = array_keys($themes[$theme]->base_themes);
      $theme_keys[] = $theme;
    }
    else {
      $theme_keys = [
        $theme,
      ];
    }

    // Save the name of the current theme (if any), so that we can temporarily
    // override the current theme and allow theme_get_setting() to work
    // without having to pass the theme name to it.
    $default_active_theme = $this->themeManager
      ->getActiveTheme();
    $default_theme = $default_active_theme
      ->getName();

    /** @var \Drupal\Core\Theme\ThemeInitialization $theme_initialization */
    $theme_initialization = \Drupal::service('theme.initialization');
    $this->themeManager
      ->setActiveTheme($theme_initialization
      ->getActiveThemeByName($theme));

    // Process the theme and all its base themes.
    foreach ($theme_keys as $theme) {

      // Include the theme-settings.php file.
      $theme_path = drupal_get_path('theme', $theme);
      $theme_settings_file = $theme_path . '/theme-settings.php';
      $theme_file = $theme_path . '/' . $theme . '.theme';
      $filenames = [
        $theme_settings_file,
        $theme_file,
      ];
      foreach ($filenames as $filename) {
        if (file_exists($filename)) {
          require_once $filename;

          // The file must be required for the cached form too.
          $files = $form_state
            ->getBuildInfo()['files'];
          if (!in_array($filename, $files)) {
            $files[] = $filename;
          }
          $form_state
            ->addBuildInfo('files', $files);
        }
      }

      // Call theme-specific settings.
      $function = $theme . '_form_system_theme_settings_alter';
      if (function_exists($function)) {
        $function($form, $form_state);
      }
    }

    // Restore the original current theme.
    if (isset($default_theme)) {
      $this->themeManager
        ->setActiveTheme($default_active_theme);
    }
    else {
      $this->themeManager
        ->resetActiveTheme();
    }
  }
  return $form;
}