X-Git-Url: http://www.aleph1.co.uk/gitweb/?a=blobdiff_plain;f=web%2Fcore%2Fmodules%2Fsystem%2Fsrc%2FForm%2FThemeSettingsForm.php;fp=web%2Fcore%2Fmodules%2Fsystem%2Fsrc%2FForm%2FThemeSettingsForm.php;h=f5cfb090826095502702deace675154248c0642b;hb=a2bd1bf0c2c1f1a17d188f4dc0726a45494cefae;hp=0000000000000000000000000000000000000000;hpb=57c063afa3f66b07c4bbddc2d6129a96d90f0aad;p=yaffs-website
diff --git a/web/core/modules/system/src/Form/ThemeSettingsForm.php b/web/core/modules/system/src/Form/ThemeSettingsForm.php
new file mode 100644
index 000000000..f5cfb0908
--- /dev/null
+++ b/web/core/modules/system/src/Form/ThemeSettingsForm.php
@@ -0,0 +1,500 @@
+moduleHandler = $module_handler;
+ $this->themeHandler = $theme_handler;
+ $this->mimeTypeGuesser = $mime_type_guesser;
+ $this->themeManager = $theme_manager;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public static function create(ContainerInterface $container) {
+ return new static(
+ $container->get('config.factory'),
+ $container->get('module_handler'),
+ $container->get('theme_handler'),
+ $container->get('file.mime_type.guesser'),
+ $container->get('theme.manager')
+ );
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getFormId() {
+ return 'system_theme_settings';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function getEditableConfigNames() {
+ return $this->editableConfig;
+ }
+
+ /**
+ * {@inheritdoc}
+ *
+ * @param string $theme
+ * The theme name.
+ */
+ 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.")
+ ];
+ }
+
+ 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.")
+ ];
+ }
+
+ // 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 (file_uri_scheme($original_path) == 'public') {
+ $friendly_path = file_uri_target($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: @implicit-public-file
(for a file in the public filesystem), @explicit-file
, or @local-file
.', [
+ '@implicit-public-file' => isset($friendly_path) ? $friendly_path : $default,
+ '@explicit-file' => file_uri_scheme($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.
+ $filename = DRUPAL_ROOT . '/' . $themes[$theme]->getPath() . '/theme-settings.php';
+ if (file_exists($filename)) {
+ require_once $filename;
+ }
+
+ // 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;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function validateForm(array &$form, FormStateInterface $form_state) {
+ parent::validateForm($form, $form_state);
+
+ if ($this->moduleHandler->moduleExists('file')) {
+ // Handle file uploads.
+ $validators = ['file_validate_is_image' => []];
+
+ // Check for a new uploaded logo.
+ $file = file_save_upload('logo_upload', $validators, FALSE, 0);
+ if (isset($file)) {
+ // File upload was attempted.
+ if ($file) {
+ // Put the temporary file in form_values so we can save it on submit.
+ $form_state->setValue('logo_upload', $file);
+ }
+ else {
+ // File upload failed.
+ $form_state->setErrorByName('logo_upload', $this->t('The logo could not be uploaded.'));
+ }
+ }
+
+ $validators = ['file_validate_extensions' => ['ico png gif jpg jpeg apng svg']];
+
+ // Check for a new uploaded favicon.
+ $file = file_save_upload('favicon_upload', $validators, FALSE, 0);
+ if (isset($file)) {
+ // File upload was attempted.
+ if ($file) {
+ // Put the temporary file in form_values so we can save it on submit.
+ $form_state->setValue('favicon_upload', $file);
+ }
+ else {
+ // File upload failed.
+ $form_state->setErrorByName('favicon_upload', $this->t('The favicon could not be uploaded.'));
+ }
+ }
+
+ // When intending to use the default logo, unset the logo_path.
+ if ($form_state->getValue('default_logo')) {
+ $form_state->unsetValue('logo_path');
+ }
+
+ // When intending to use the default favicon, unset the favicon_path.
+ if ($form_state->getValue('default_favicon')) {
+ $form_state->unsetValue('favicon_path');
+ }
+
+ // If the user provided a path for a logo or favicon file, make sure a file
+ // exists at that path.
+ if ($form_state->getValue('logo_path')) {
+ $path = $this->validatePath($form_state->getValue('logo_path'));
+ if (!$path) {
+ $form_state->setErrorByName('logo_path', $this->t('The custom logo path is invalid.'));
+ }
+ }
+ if ($form_state->getValue('favicon_path')) {
+ $path = $this->validatePath($form_state->getValue('favicon_path'));
+ if (!$path) {
+ $form_state->setErrorByName('favicon_path', $this->t('The custom favicon path is invalid.'));
+ }
+ }
+ }
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function submitForm(array &$form, FormStateInterface $form_state) {
+ parent::submitForm($form, $form_state);
+
+ $config_key = $form_state->getValue('config_key');
+ $this->editableConfig = [$config_key];
+ $config = $this->config($config_key);
+
+ // Exclude unnecessary elements before saving.
+ $form_state->cleanValues();
+ $form_state->unsetValue('var');
+ $form_state->unsetValue('config_key');
+
+ $values = $form_state->getValues();
+
+ // If the user uploaded a new logo or favicon, save it to a permanent location
+ // and use it in place of the default theme-provided file.
+ if (!empty($values['logo_upload'])) {
+ $filename = file_unmanaged_copy($values['logo_upload']->getFileUri());
+ $values['default_logo'] = 0;
+ $values['logo_path'] = $filename;
+ }
+ if (!empty($values['favicon_upload'])) {
+ $filename = file_unmanaged_copy($values['favicon_upload']->getFileUri());
+ $values['default_favicon'] = 0;
+ $values['favicon_path'] = $filename;
+ $values['toggle_favicon'] = 1;
+ }
+ unset($values['logo_upload']);
+ unset($values['favicon_upload']);
+
+ // If the user entered a path relative to the system files directory for
+ // a logo or favicon, store a public:// URI so the theme system can handle it.
+ if (!empty($values['logo_path'])) {
+ $values['logo_path'] = $this->validatePath($values['logo_path']);
+ }
+ if (!empty($values['favicon_path'])) {
+ $values['favicon_path'] = $this->validatePath($values['favicon_path']);
+ }
+
+ if (empty($values['default_favicon']) && !empty($values['favicon_path'])) {
+ $values['favicon_mimetype'] = $this->mimeTypeGuesser->guess($values['favicon_path']);
+ }
+
+ theme_settings_convert_to_config($values, $config)->save();
+ }
+
+ /**
+ * Helper function for the system_theme_settings form.
+ *
+ * Attempts to validate normal system paths, paths relative to the public files
+ * directory, or stream wrapper URIs. If the given path is any of the above,
+ * returns a valid path or URI that the theme system can display.
+ *
+ * @param string $path
+ * A path relative to the Drupal root or to the public files directory, or
+ * a stream wrapper URI.
+ * @return mixed
+ * A valid path that can be displayed through the theme system, or FALSE if
+ * the path could not be validated.
+ */
+ protected function validatePath($path) {
+ // Absolute local file paths are invalid.
+ if (drupal_realpath($path) == $path) {
+ return FALSE;
+ }
+ // A path relative to the Drupal root or a fully qualified URI is valid.
+ if (is_file($path)) {
+ return $path;
+ }
+ // Prepend 'public://' for relative file paths within public filesystem.
+ if (file_uri_scheme($path) === FALSE) {
+ $path = 'public://' . $path;
+ }
+ if (is_file($path)) {
+ return $path;
+ }
+ return FALSE;
+ }
+
+}