function ThemeSettingsForm::buildForm

Same name in other branches
  1. 9 core/modules/system/src/Form/ThemeSettingsForm.php \Drupal\system\Form\ThemeSettingsForm::buildForm()
  2. 8.9.x core/modules/system/src/Form/ThemeSettingsForm.php \Drupal\system\Form\ThemeSettingsForm::buildForm()
  3. 11.x core/modules/system/src/Form/ThemeSettingsForm.php \Drupal\system\Form\ThemeSettingsForm::buildForm()

Parameters

array $form: An associative array containing the structure of the form.

\Drupal\Core\Form\FormStateInterface $form_state: The current state of the form.

string $theme: The theme name.

Overrides ConfigFormBase::buildForm

File

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

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' => $this->t('User pictures in posts'),
        'comment_user_picture' => $this->t('User pictures in comments'),
        'comment_user_verification' => $this->t('User verification status in comments'),
        'favicon' => $this->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' => $this->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' => $this->t('Logo image'),
            '#open' => TRUE,
        ];
        $form['logo']['default_logo'] = [
            '#type' => 'checkbox',
            '#title' => $this->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' => $this->t('Path to custom logo'),
            '#default_value' => theme_get_setting('logo.path', $theme),
        ];
        $form['logo']['settings']['logo_upload'] = [
            '#type' => 'file',
            '#title' => $this->t('Upload logo image'),
            '#description' => $this->t("If you don't have direct file access to the server, use this field to upload your logo."),
            '#upload_validators' => [
                'FileExtension' => [
                    'extensions' => 'png gif jpg jpeg apng svg',
                ],
            ],
        ];
    }
    if ((!$theme || in_array('favicon', $features)) && $this->moduleHandler
        ->moduleExists('file')) {
        $form['favicon'] = [
            '#type' => 'details',
            '#title' => $this->t('Favicon'),
            '#open' => TRUE,
            '#description' => $this->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' => $this->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' => $this->t('Path to custom icon'),
            '#default_value' => theme_get_setting('favicon.path', $theme),
        ];
        $form['favicon']['settings']['favicon_upload'] = [
            '#type' => 'file',
            '#title' => $this->t('Upload favicon image'),
            '#description' => $this->t("If you don't have direct file access to the server, use this field to upload your shortcut icon."),
            '#upload_validators' => [
                'FileExtension' => [
                    'extensions' => 'ico png gif jpg jpeg apng svg webp',
                ],
            ],
        ];
    }
    // 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 = $this->themeHandler
                    ->getTheme($theme)
                    ->getPath() . '/' . $default;
            }
            else {
                $local_file = $this->themeManager
                    ->getActiveTheme()
                    ->getPath() . '/' . $default;
            }
            $element['#description'] = $this->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' => $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' => $this->t('Theme-engine-specific settings'),
                '#open' => TRUE,
                '#description' => $this->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 = $this->themeHandler
                ->getTheme($theme)
                ->getPath();
            $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;
}

Buggy or inaccurate documentation? Please file an issue. Need support? Need help programming? Connect with the Drupal community.