/** * Form submit handler for the theme settings form. * @param $form * @param $form_state */ function at_generator_submit_generator(&$form, &$form_state) { $build_info = $form_state->getBuildInfo(); $values = $form_state->getValues(); $theme = $build_info['args'][0]; // Generate a new theme. if (!empty($values['generate']['generate_machine_name']) && $theme == 'at_generator') { $fileOperations = new FileOperations(); $directoryOperations = new DirectoryOperations(); // Prepare form values and set them into variables. $machine_name = $values['generate']['generate_machine_name']; $friendly_name = Html::escape($values['generate']['generate_friendly_name']); $subtheme_type = $values['generate']['generate_type']; //$skin_base_theme = $values['generate']['generate_skin_base'] ?: 0; $clone_source = $values['generate']['generate_clone_source'] ?: ''; $templates = $values['generate']['options']['generate_templates']; $uikit = $values['generate']['options']['generate_uikit']; $color = $values['generate']['options']['generate_color']; $theme_settings_file = $values['generate']['options']['generate_themesettingsfile']; $description = preg_replace('/[^A-Za-z0-9. ]/', '', Html::escape($values['generate']['options']['generate_description'])); $version = Html::escape($values['generate']['options']['generate_version']); // Initialize variables. $source = ''; $source_theme = ''; // Generated date time for descriptions. $datetime = \Drupal::service('date.formatter')->format(REQUEST_TIME, 'custom', 'D jS, M - G:i'); // Generic description if the desc field is not set. $generic_description = 'Sub theme of AT Core'; // Path to themes $path = drupal_get_path('theme', 'at_core'); $at_generator_path = drupal_get_path('theme', 'at_generator'); // Path to where we will save the cloned theme. // This could be configurable? $at_core_path_parts = explode("/", $path); if (in_array('contrib', $at_core_path_parts)) { $target_path = array('themes', 'custom'); } else { $target_path = array('themes'); } $target_dir = $directoryOperations->directoryPrepare($target_path); $target = "{$target_dir}/{$machine_name}"; if (!is_writable('themes')) { drupal_set_message(t('The "themes" directory is not writable. To generate a new theme reset permissions for the "@themespath" directory so it is writable, e.g. chmod themes 0755.', array('@themespath' => base_path() . 'themes')), 'error'); return; } // Array of UIKit tools. $uikit_tools = array('package.json', '.csslintrc', 'Gruntfile.js', 'Gemfile', 'Gemfile.lock'); // Standard and Minimal variables. if ($subtheme_type === 'standard') { $source_theme = 'THEMENAME'; $source = $at_generator_path . '/components/starterkit'; } // Clone variables. if ($subtheme_type === 'clone') { $source_theme = $clone_source; $source = drupal_get_path('theme', $source_theme); } // Skin variables. // if ($subtheme_type === 'skin') { // $source_theme = $skin_base_theme; // $source = drupal_get_path('theme', $source_theme); // } // All themes have configuration. $configuration_files = $directoryOperations->directoryScan("{$source}/config/install"); // Files to strip replace strings $info_file = "{$target}/{$machine_name}.info.yml"; $library_file = "{$target}/{$machine_name}.libraries.yml"; $shortcodes_file = "{$target}/{$machine_name}.shortcodes.yml"; // Begin generation. //------------------------------------------------------------------------------------------------ // Recursively copy the source theme. if (is_dir($source)) { $directoryOperations->directoryRecursiveCopy($source, $target); } // Generated CSS files. $generated_css = $directoryOperations->directoryScan("{$source}/styles/css/generated"); foreach ($generated_css as $old_css_file) { $new_css_file = str_replace($source_theme, $machine_name, $old_css_file); $fileOperations->fileRename("{$target}/styles/css/generated/{$old_css_file}", "{$target}/styles/css/generated/{$new_css_file}"); } // UIKit and Color if ($subtheme_type === 'standard') { // UIKit if ($uikit === 0) { $directoryOperations->directoryRemove("{$target}/styles/uikit"); // remove files like GEM, Gruntfile.js etc foreach ($uikit_tools as $tool) { unlink("{$target}/{$tool}"); } // Remove all SASS map files and references. array_map('unlink', glob("{$target}/styles/css/components/*.map")); $component_css_files = $directoryOperations->directoryScan("{$target}/styles/css/components"); foreach ($component_css_files as $component_file_key => $component_file) { $map_string = '/*# sourceMappingURL=' . str_replace('.css', '.css.map', $component_file) . ' */'; $fileOperations->fileStrReplace("{$target}/styles/css/components/{$component_file}", $map_string, ''); } } // Color. if ($color === 0) { $directoryOperations->directoryRemove("{$target}/color"); } } // UIKit skins. //if ($subtheme_type === 'skin') { // $directoryOperations->directoryRemove("$target/styles/uikit"); //} // Templates. if ($subtheme_type === 'standard') { $fileOperations->fileStrReplace("{$target}/templates/generated/page.html.twig", 'THEMENAME', $machine_name); if ($templates === 1) { $directoryOperations->directoryRecursiveCopy("{$path}/templates", "{$target}/templates"); } } if ($subtheme_type === 'clone') { $cloned_templates = $directoryOperations->directoryScan("{$target}/templates/generated"); foreach ($cloned_templates as $cloned_template) { $fileOperations->fileStrReplace("{$target}/templates/generated/{$cloned_template}", $source_theme, $machine_name); } } //if ($subtheme_type === 'skin') { // $directoryOperations->directoryRemove("$target/templates"); //} // .theme if ($subtheme_type === 'standard') { $fileOperations->fileRename("{$target}/{$source_theme}.theme", "{$target}/{$machine_name}.theme"); $fileOperations->fileStrReplace("{$target}/{$machine_name}.theme", 'HOOK', $machine_name); } if ($subtheme_type === 'clone') { $fileOperations->fileRename("{$target}/{$source_theme}.theme", "{$target}/{$machine_name}.theme"); $fileOperations->fileStrReplace("{$target}/{$machine_name}.theme", $source_theme, $machine_name); } // if ($subtheme_type === 'skin') { // $fileOperations->fileRename("$target/$source_theme.theme", "$target/$machine_name.theme"); // $skin_theme = file_get_contents("$at_generator_path/components/starterkit_skin/SKIN.theme"); // $fileOperations->fileReplace($skin_theme, "$target/$machine_name.theme"); // $fileOperations->fileStrReplace("$target/$machine_name.theme", 'HOOK', $machine_name); // } // libraries $fileOperations->fileRename("{$target}/{$source_theme}.libraries.yml", $library_file); // if ($subtheme_type === 'skin') { // $skin_libraries = file_get_contents("$at_generator_path/components/starterkit_skin/SKIN.libraries.yml"); // $fileOperations->fileReplace($skin_libraries, "$target/$library_file"); // $directoryOperations->directoryRemove("$target/styles/css/components"); // $directoryOperations->directoryRecursiveCopy("$at_generator_path/components", "$target/styles/css"); // } // theme-settings.php if ($subtheme_type === 'standard') { if ($theme_settings_file === 1) { $fileOperations->fileStrReplace("{$target}/theme-settings.php", 'HOOK', $machine_name); } else { $directoryOperations->directoryRemove("{$target}/theme-settings.php"); } } if ($subtheme_type === 'clone') { $fileOperations->fileStrReplace("{$target}/theme-settings.php", $source_theme, $machine_name); } // if ($subtheme_type === 'skin') { // $directoryOperations->directoryRemove("$target/theme-settings.php"); // } // Config. foreach ($configuration_files as $old_config_file) { $new_config_file = str_replace($source_theme, $machine_name, $old_config_file); $fileOperations->fileRename("{$target}/config/install/{$old_config_file}", "{$target}/config/install/{$new_config_file}"); $fileOperations->fileStrReplace("{$target}/config/install/{$new_config_file}", 'TARGET', $target); $fileOperations->fileStrReplace("{$target}/config/install/{$new_config_file}", $source_theme, $machine_name); } // Skin and clone need their source themes configuration. //if ($subtheme_type === 'skin' || $subtheme_type === 'clone') { if ($subtheme_type === 'clone') { $source_config = \Drupal::config($source_theme . '.settings')->get(); // Empty if the source theme has never been installed, in which case it // should be safe to assume there is no new configuration worth saving. if (!empty($source_config)) { $old_config = "{$target}/config/install/{$machine_name}.settings.yml"; $new_config = Yaml::encode($source_config); $find_generated_files = "themes/{$source_theme}/styles/css/generated"; $replace_generated_files = "themes/{$machine_name}/styles/css/generated"; $new_config = str_replace($find_generated_files, $replace_generated_files, $new_config); $fileOperations->fileReplace($new_config, $old_config); $fileOperations->fileStrReplace("{$target}/config/install/{$new_config_file}", $source_theme, $machine_name); } } // Info. $fileOperations->fileRename("{$target}/{$source_theme}.info.yml", $info_file); // Shortcodes. $fileOperations->fileRename("{$target}/{$source_theme}.shortcodes.yml", $shortcodes_file); // Parse, rebuild and save the themes info.yml file. $parser = new Parser(); $theme_info_data = $parser->parse(file_get_contents($info_file)); // Name and theme type. $theme_info_data['name'] = "{$friendly_name}"; $theme_info_data['type'] = "theme"; // Base theme. // if ($subtheme_type === 'skin') { // $theme_info_data['base theme'] = $source_theme; // } // Description. $base_theme = $theme_info_data['base theme']; if ($subtheme_type === 'clone') { $description = $description ?: 'Clone of ' . $source_theme; } // if ($subtheme_type === 'skin') { // $base_theme = $source_theme; // $description = $description ?: 'Skin theme'; // } $description = $description ?: $generic_description; $theme_info_data['description'] = "{$description} (base theme: {$base_theme}).<br /> Generated: {$datetime}"; // alt text. $theme_info_data['alt text'] = "Screenshot for {$friendly_name}"; // Version. $theme_info_data['version'] = $version ? str_replace(' ', '-', trim($version)) : '8.0.x'; // Regions. foreach ($theme_info_data['regions'] as $region_key => $region_name) { $theme_info_data['regions'][$region_key] = "{$region_name}"; } // Unset stuff we don't want or need. unset($theme_info_data['hidden']); unset($theme_info_data['project']); unset($theme_info_data['datestamp']); // Libraries. if (isset($theme_info_data['libraries-extend']['quickedit/quickedit'])) { $theme_info_data['libraries-extend']['quickedit/quickedit'] = array($machine_name . '/quickedit'); } // Save the info file. $rebuilt_info = $fileOperations->fileBuildInfoYml($theme_info_data); $fileOperations->fileReplace($rebuilt_info, $info_file); // Set messages, however we may need more validation? //---------------------------------------------------------------------- // system message for Reports. $logger_message = t('A new theme <b>@theme_name</b>, with then machine name: <code><b>@machine_name</b></code>, has been generated.', array('@theme_name' => $friendly_name, '@machine_name' => $machine_name)); \Drupal::logger('at_generator')->notice($logger_message); // Message for the user. drupal_set_message(t("<p>A new theme <b>@theme_name</b>, with then machine name: <code><b>@machine_name</b></code>, has been generated.</p><p>You can find your theme here: <code><b>@theme_path</b></code> </p>", array('@theme_name' => $friendly_name, '@machine_name' => $machine_name, '@theme_path' => $target, '@performance_settings' => base_path() . 'admin/config/development/performance')), 'status'); // Refresh data. system_list_reset(); \Drupal::service('theme_handler')->rebuildThemeData(); } else { drupal_set_message(t('Bummer, something went wrong, please try again.')); } }
/** * {@inheritdoc} */ public function saveLayoutSuggestionsMarkup() { $template_suggestions = array(); $fileOperations = new FileOperations(); $directoryOperations = new DirectoryOperations(); if (!empty($this->form_values['settings_suggestions'])) { $template_suggestions = $this->form_values['settings_suggestions']; } if (!empty($this->form_values['ts_name'])) { $template_suggestions['page__' . $this->form_values['ts_name']] = 'page__' . $this->form_values['ts_name']; } // Don't regenerate templates to be deleted. foreach ($this->form_values as $values_key => $values_value) { if (substr($values_key, 0, 18) === 'delete_suggestion_') { if ($values_value === 1) { $delete_suggestion_keys[] = Unicode::substr($values_key, 18); } } } if (!empty($delete_suggestion_keys)) { foreach ($delete_suggestion_keys as $template_to_remove) { unset($template_suggestions[$template_to_remove]); } } // Template path. $template_file = $this->layout_path . '/' . $this->layout_name . '.html.twig'; // Path to target theme where the template will be saved. $path = drupal_get_path('theme', $this->theme_name); // Remove if this exists, its now deprecated, this is a BC layer so to speak. $directoryOperations->directoryRemove($path . '/templates/page'); $template_directory = $path . '/templates/generated'; // Check and create the templates directory if does not exist. if (!file_exists($path . '/templates')) { \Drupal::service('file_system')->mkdir($path . '/templates'); } if (!file_exists($template_directory)) { \Drupal::service('file_system')->mkdir($template_directory); } // Initialize vars. $row_regions = array(); $templates = array(); $saved_templates = array(); // We have to save every template every time, in case a row has been added to the layout, all template MUST update. // This could be changed later to only do this IF a row has been added, we're not that flash right now :) foreach ($template_suggestions as $suggestion_key => $suggestions_name) { $output = array(); $suggestion_key = Html::escape($suggestion_key); // Doc block. $doc = array(); $doc[$suggestion_key][] = '{#'; $doc[$suggestion_key][] = '/**'; $doc[$suggestion_key][] = ' * ' . $this->layout_name . ' ' . $suggestion_key . ' template.'; $doc[$suggestion_key][] = ' * Generated on: ' . date(DATE_RFC822); $doc[$suggestion_key][] = ' */'; $doc[$suggestion_key][] = '#}' . "\n"; $docblock[$suggestion_key] = implode("\n", $doc[$suggestion_key]); // Attach layout. $generated_files_path = $this->form_values['settings_generated_files_path']; $layout_file = $this->theme_name . '.layout.' . str_replace('_', '-', $suggestion_key) . '.css'; if (file_exists($generated_files_path . '/' . $layout_file)) { $library = $this->theme_name . '/' . $this->theme_name . '.layout.' . $suggestion_key; } else { $library = $this->theme_name . '/' . $this->theme_name . '.layout.page'; } $attach_layout = "{{ attach_library('{$library}') }}"; // Get the template file, if not found attempt to generate template // code programmatically. if (file_exists($template_file)) { $template = file_get_contents($template_file); } else { foreach ($this->layout_config['rows'] as $row => $row_values) { // Row attributes. $attributes[$row]['class'][] = 'l-pr page__row'; $attributes[$row]['class'][] = 'pr-' . $row; foreach ($row_values['attributes'] as $attribute_type => $attribute_values) { if (is_array($attribute_values)) { $attributes[$row][$attribute_type][] = implode(' ', $attribute_values); } else { $attributes[$row][$attribute_type][] = $attribute_values; } } ksort($attributes[$row], SORT_STRING); foreach ($attributes[$row] as $attr_type => $attr_array_vales) { $attr_array_vales = array_unique($attr_array_vales); $this_row_attr[$row][$attr_type] = $attr_type . '="' . implode(' ', $attr_array_vales) . '"'; } $wrapper_element[$suggestion_key] = 'div'; if ($row == 'header' || $row == 'footer') { $wrapper_element[$suggestion_key] = $row; } $output[$suggestion_key][$row]['prefix'] = ' {% if ' . $row . '.has_regions == true %}'; $output[$suggestion_key][$row]['wrapper_open'] = ' <' . $wrapper_element[$suggestion_key] . '{{ ' . $row . '.wrapper_attributes }}>'; $output[$suggestion_key][$row]['container_open'] = ' <div{{ ' . $row . '.container_attributes }}>'; foreach ($row_values['regions'] as $region_name => $region_value) { $row_regions[$suggestion_key][$row][] = ' {{ page.' . $region_name . ' }}'; } $output[$suggestion_key][$row]['regions'] = implode("\n", $row_regions[$suggestion_key][$row]); $output[$suggestion_key][$row]['container_close'] = ' </div>'; $output[$suggestion_key][$row]['wrapper_close'] = ' </' . $wrapper_element[$suggestion_key] . '>'; $output[$suggestion_key][$row]['suffix'] = ' {% endif %}' . "\n"; } $generated[$suggestion_key][] = '<div{{ attributes }}>' . "\n"; foreach ($output[$suggestion_key] as $row_output) { $generated[$suggestion_key][] = implode("\n", $row_output); } $generated[$suggestion_key][] = " {{ attribution }}" . "\n"; $generated[$suggestion_key][] = '</div>' . "\n"; $template[$suggestion_key] = implode($generated[$suggestion_key]); } // Prepend the docblock to the template markup. $template_markup[$suggestion_key] = $docblock[$suggestion_key] . $attach_layout . "\n" . $template[$suggestion_key]; // Set the template file, either it's page or a page suggestion. if ($suggestion_key !== 'page') { $template_file = str_replace('_', '-', $suggestion_key) . '.html.twig'; } else { $template_file = 'page.html.twig'; } // Set the template path. $template_path = $template_directory . '/' . $template_file; // Build array of files to be saved. $templates[$suggestion_key]['markup'] = $template_markup[$suggestion_key]; $templates[$suggestion_key]['template_path'] = $template_path; $templates[$suggestion_key]['template_name'] = $template_file; // Create a backup. if ($this->form_values['settings_enable_backups'] == 1) { $backup_path = $directoryOperations->directoryPrepare($backup_file_path = array($path, 'backup', 'templates')); //Add a date time string to make unique and for easy identification, // save as .txt to avoid conflicts. $backup_file = $template_file . '.' . date(DATE_ISO8601) . '.txt'; $file_paths = array('copy_source' => $template_path, 'copy_dest' => $backup_path . '/' . $template_file, 'rename_oldname' => $backup_path . '/' . $template_file, 'rename_newname' => $backup_path . '/' . $backup_file); $fileOperations->fileCopyRename($file_paths); } } foreach ($templates as $suggestion => $template_values) { if (!file_exists($templates[$suggestion]['template_path'])) { $new_template = $templates[$suggestion]['template_name']; $new_template_message = t('It looks like you generated a new template: <b>@new_template</b>. Save the layout settings again so they will take effect.', array('@new_template' => $new_template)); } file_unmanaged_save_data($templates[$suggestion]['markup'], $templates[$suggestion]['template_path'], FILE_EXISTS_REPLACE); if (file_exists($templates[$suggestion]['template_path'])) { $saved_templates[] = $templates[$suggestion]['template_name']; } } if (!empty($saved_templates)) { $saved_templates_message_list = array('#theme' => 'item_list', '#items' => $saved_templates); drupal_set_message(t('The following <b>templates</b> were generated in: <code>@template_directory</code> @saved_templates', array('@saved_templates' => \Drupal::service('renderer')->renderPlain($saved_templates_message_list), '@template_directory' => $template_directory . '/')), 'status'); } if (isset($new_template_message)) { drupal_set_message($new_template_message, 'status'); } }
/** * Generate a sub-theme. * * Need to validate some of this stuff and write proper error handling for when things * go wrong, rather than just saying hooray, it worked, when no, it did not... */ public function generateTheme($values) { $fileOperations = new FileOperations(); $directoryOperations = new DirectoryOperations(); // Prepare form values and set them into variables $machine_name = $values['generate']['generate_machine_name']; $friendly_name = SafeMarkup::checkPlain($values['generate']['generate_friendly_name']); $subtheme_type = $values['generate']['generate_type']; $skin_base_theme = $values['generate']['generate_skin_base'] ?: 0; $clone_source = $values['generate']['generate_clone_source'] ?: ''; $templates = $values['generate']['options']['generate_templates']; $uikit = $values['generate']['options']['generate_uikit']; $color = $values['generate']['options']['generate_color']; //$dottheme_file = $values['generate']['options']['generate_themefile']; $theme_settings_file = $values['generate']['options']['generate_themesettingsfile']; $description = preg_replace('/[^A-Za-z0-9. ]/', '', $values['generate']['options']['generate_description']); $version = $values['generate']['options']['generate_version']; // Generic description if the desc field is not set $generic_decription = 'Sub theme of AT Core'; // Path to themes $path = drupal_get_path('theme', 'at_core'); $at_generator_path = drupal_get_path('theme', 'at_generator'); // Path to where we will save the cloned theme // This could be configurable? //$target = $path . '/../../' . $machine_name; $at_core_path_parts = explode("/", $path); if (in_array('contrib', $at_core_path_parts)) { $target_path = array('themes', 'custom'); } else { $target_path = array('themes'); } $target_dir = $directoryOperations->directoryPrepare($target_path); $target = "$target_dir/$machine_name"; // Array of UIKit tools $uikit_tools = array( 'package.json', '.csslintrc', 'Gruntfile.js', 'Gemfile', 'Gemfile.lock', ); // Standard and Minimal variables if ($subtheme_type === 'standard') { $source_theme = 'THEMENAME'; $source = $at_generator_path . '/components/starterkit'; } // Clone variables if ($subtheme_type === 'clone') { $source_theme = $clone_source; $source = drupal_get_path('theme', $source_theme); } // Skin variables if ($subtheme_type === 'skin') { $source_theme = $skin_base_theme; $source = drupal_get_path('theme', $source_theme); } // All themes have configuration $configuration_files = $directoryOperations->directoryScan("$source/config/install"); // Files to strip replace strings $info_file = "$target/$machine_name.info.yml"; $library_file = "$target/$machine_name.libraries.yml"; $shortcodes_file = "$target/$machine_name.shortcodes.yml"; // Begin generation //------------------------------------------------------------------------------------------------ // Recursively copy the source theme if (is_dir($source)) { $directoryOperations->directoryRecursiveCopy($source, $target); } // Genearated CSS files $generated_css = $directoryOperations->directoryScan("$source/styles/css/generated"); foreach ($generated_css as $old_css_file) { $new_css_file = str_replace($source_theme, $machine_name, $old_css_file); $fileOperations->fileRename("$target/styles/css/generated/$old_css_file", "$target/styles/css/generated/$new_css_file"); } // UIKit and Color if ($subtheme_type === 'standard') { // UIKit if ($uikit === 0) { $directoryOperations->directoryRemove("$target/styles/uikit"); // remove files like GEM, Gruntfile.js etc foreach ($uikit_tools as $tool) { unlink("$target/$tool"); } // remove all the map files from the css dir "$target/styles/uikit" array_map('unlink', glob("$target/styles/css/components/*.map")); } // Color if ($color === 0) { $directoryOperations->directoryRemove("$target/color"); //$directoryOperations->directoryRemove("$target/styles/css/colors.css"); // If UIKit and not color //if ($uikit === 1) { //$directoryOperations->directoryRemove("$target/styles/uikit/colors.scss"); //$directoryOperations->directoryRemove("$target/styles/uikit/components/_colors.scss"); //} } } // UIKit skins if ($subtheme_type === 'skin') { $directoryOperations->directoryRemove("$target/styles/uikit"); } // Templates if ($subtheme_type === 'standard') { $fileOperations->fileStrReplace("$target/templates/page/page.html.twig", 'THEMENAME', $machine_name); if ($templates === 1) { $directoryOperations->directoryRecursiveCopy("$path/templates", "$target/templates"); } } if ($subtheme_type === 'skin') { $directoryOperations->directoryRemove("$target/templates"); } // .theme if ($subtheme_type === 'standard') { $fileOperations->fileRename("$target/$source_theme.theme", "$target/$machine_name.theme"); $fileOperations->fileStrReplace("$target/$machine_name.theme", 'HOOK', $machine_name); } if ($subtheme_type === 'clone') { $fileOperations->fileRename("$target/$source_theme.theme", "$target/$machine_name.theme"); $fileOperations->fileStrReplace("$target/$machine_name.theme", $source_theme, $machine_name); } if ($subtheme_type === 'skin') { $fileOperations->fileRename("$target/$source_theme.theme", "$target/$machine_name.theme"); $skin_theme = file_get_contents("$at_generator_path/components/starterkit_skin/SKIN.theme"); $fileOperations->fileReplace($skin_theme, "$target/$machine_name.theme"); $fileOperations->fileStrReplace("$target/$machine_name.theme", 'HOOK', $machine_name); } // libraries $fileOperations->fileRename("$target/$source_theme.libraries.yml", $library_file); //if ($subtheme_type === 'standard') { //if ($color === 0) { // $fileOperations->fileStrReplace($library_file, 'styles/css/colors.css: {}', ''); //} //} if ($subtheme_type === 'skin') { $skin_libraries = file_get_contents("$at_generator_path/components/starterkit_skin/SKIN.libraries.yml"); $fileOperations->fileReplace($skin_libraries, "$target/$library_file"); $directoryOperations->directoryRemove("$target/styles/css/components"); $directoryOperations->directoryRecursiveCopy("$at_generator_path/components", "$target/styles/css"); //$fileOperations->fileStrReplace($library_file, 'styles/css/styles.css: {}', "styles/css/$machine_name-styles.css: {}"); //$directoryOperations->directoryRemove("$target/styles/css/styles.css"); //$fileOperations->fileRename("$target/styles/css/styles.css", "$target/styles/css/$machine_name-styles.css"); //$skin_styles = '/* Styles for ' . $machine_name . ' */'; //$fileOperations->fileReplace($skin_styles, "$target/styles/css/$machine_name-styles.css"); } // theme-settings.php if ($subtheme_type === 'standard') { if ($theme_settings_file === 1) { $fileOperations->fileStrReplace("$target/theme-settings.php", 'HOOK', $machine_name); } else { $directoryOperations->directoryRemove("$target/theme-settings.php"); } } if ($subtheme_type === 'clone') { $fileOperations->fileStrReplace("$target/theme-settings.php", $source_theme, $machine_name); } if ($subtheme_type === 'skin') { $directoryOperations->directoryRemove("$target/theme-settings.php"); } // Config foreach ($configuration_files as $old_config_file) { $new_config_file = str_replace($source_theme, $machine_name, $old_config_file); $fileOperations->fileRename("$target/config/install/$old_config_file", "$target/config/install/$new_config_file"); $fileOperations->fileStrReplace("$target/config/install/$new_config_file", 'TARGET', $target); $fileOperations->fileStrReplace("$target/config/install/$new_config_file", $source_theme, $machine_name); } // Skin and clone need their source themes configuration if ($subtheme_type === 'skin' || $subtheme_type === 'clone') { $source_config = \Drupal::config($source_theme . '.settings')->get(); // Empty if the source theme has never been installed, in which case it should be safe to assume // there is no new configuration worth saving. if (!empty($source_config)) { $old_config = "$target/config/install/$machine_name.settings.yml"; $new_config = Yaml::encode($source_config); $find_generated_files = "themes/$source_theme/styles/css/generated"; $replace_generated_files = "themes/$machine_name/styles/css/generated"; $new_config = str_replace($find_generated_files, $replace_generated_files, $new_config); $fileOperations->fileReplace($new_config, $old_config); } } // Info $fileOperations->fileRename("$target/$source_theme.info.yml", $info_file); // Shortcodes $fileOperations->fileRename("$target/$source_theme.shortcodes.yml", $shortcodes_file); // Parse, rebuild and save the themes info.yml file. $parser = new Parser(); $theme_info_data = $parser->parse(file_get_contents($info_file)); // Name and theme type $theme_info_data['name'] = "$friendly_name"; $theme_info_data['type'] = "theme"; // Base theme if ($subtheme_type === 'skin') { $theme_info_data['base theme'] = $source_theme; } // Description $base_theme = $theme_info_data['base theme']; if ($subtheme_type === 'clone') { $description = $description ?: 'Clone of ' . $source_theme; } if ($subtheme_type === 'skin') { $base_theme = $source_theme; $description = $description ?: 'Skin theme'; } $description = $description ?: $generic_decription; $theme_info_data['description'] = "$description (base theme: $base_theme)"; // alt text $theme_info_data['alt text'] = "Screenshot for $friendly_name"; // Version $version = $version ?: '8.0.x'; $theme_info_data['version'] = $version; // Regions foreach($theme_info_data['regions'] as $region_key => $region_name) { $theme_info_data['regions'][$region_key] = "$region_name"; } // Unset hidden unset($theme_info_data['hidden']); // Unset stylesheets-remove //if ($subtheme_type === 'skin') { // unset($theme_info_data['stylesheets-remove']); //} // Libraries $theme_info_data['libraries-override'] = $theme_info_data['libraries-override']; // Save the info file $rebuilt_info = $fileOperations->fileBuildInfoYml($theme_info_data); $fileOperations->fileReplace($rebuilt_info, $info_file); // Set messages, however we may need more validation? //---------------------------------------------------------------------- $generated_path = drupal_get_path('theme', $machine_name); // system message for Reports. $logger_message = t('A new theme <b>@theme_name</b>, with then machine name: <code><b>@machine_name</b></code>, has been generated.', array('@theme_name' => $friendly_name, '@machine_name' => $machine_name)); \Drupal::logger('at_generator')->notice($logger_message); // message for the user drupal_set_message(t("<p>A new theme <b>@theme_name</b>, with then machine name: <code><b>@machine_name</b></code>, has been generated.</p><p>You can find your theme here: <code><b>@theme_path</b></code> </p>", array('@theme_name' => $friendly_name, '@machine_name' => $machine_name, '@theme_path' => $target, '@performance_settings' => base_path() . 'admin/config/development/performance')), 'status'); // Refresh data. system_list_reset(); \Drupal::service('theme_handler')->rebuildThemeData(); /* // Warn about stylesheets in the new skin theme if ($subtheme_type === 'at_skin') { drupal_set_message(t('Skin themes do not inherit theme <em>settings</em>, this is important for things like Layout and Library settings. After you enable your new theme be sure to check and configure it\'s settings.', array('!theme_path' => $generated_path, '!machine_name' => $machine_name)), 'warning'); } */ }
/** * Implimentation of hook_form_system_theme_settings_alter() * * @param $form * Nested array of form elements that comprise the form. * * @param $form_state * A keyed array containing the current state of the form. */ function at_core_form_system_theme_settings_alter(&$form, &$form_state) { // Set the theme name. $build_info = $form_state->getBuildInfo(); $theme = $build_info['args'][0]; // Instantiate our Theme info object. $themeInfo = new ThemeInfo($theme); $getThemeInfo = $themeInfo->getThemeInfo('info'); // Get this themes config settings $config = \Drupal::config($theme . '.settings')->get('settings'); // Common paths. $at_core_path = drupal_get_path('theme', 'at_core'); $subtheme_path = drupal_get_path('theme', $theme); // Path to save generated CSS files. We don't want this happening for at_core or the generator. if (isset($getThemeInfo['subtheme type']) && $getThemeInfo['subtheme type'] === 'adaptive_subtheme') { $directoryOperations = new DirectoryOperations(); $generated_files_path = $directoryOperations->directoryPrepare($backup_file_path = array($subtheme_path, 'styles/css/generated')); } // Get the active themes regions so we can use this in // various other places. $theme_regions = system_region_list($theme, $show = REGIONS_VISIBLE); // Active themes active blocks $theme_blocks = entity_load_multiple_by_properties('block', ['theme' => $theme]); // Check for breakpoints module and set a warning and a flag to disable much of the theme settings if its not available $breakpoints_module = \Drupal::moduleHandler()->moduleExists('breakpoint'); if ($breakpoints_module == TRUE) { $breakpoint_groups = \Drupal::service('breakpoint.manager')->getGroups(); // Unset core breakpoint groups due to notices and other issues, until this is resolved: // SEE: https://www.drupal.org/node/2379283 unset($breakpoint_groups['toolbar']); unset($breakpoint_groups['seven']); unset($breakpoint_groups['bartik']); // Set breakpoint options, we use these in layout and other extensions like Responsive menus. foreach ($breakpoint_groups as $group_key => $group_values) { $breakpoints[$group_key] = \Drupal::service('breakpoint.manager')->getBreakpointsByGroup($group_key); } foreach($breakpoints as $group => $breakpoint_values) { if ($breakpoint_values !== array()) { $breakpoint_options[$group] = $group; } } } else { drupal_set_message(t('Adaptivetheme requires the <b>Breakpoint module</b>. Open the <a href="!extendpage" target="_blank">Extend</a> page and enable Breakpoint.', array('!extendpage' => base_path() . 'admin/modules')), 'warning'); } // Get node types (bundles). $node_types = node_type_get_types(); // View or "Display modes", the search display mode is still problematic so we will exclude it for now, // please see: https://drupal.org/node/1166114 //$node_view_modes = \Drupal::entityManager()->getViewModeOptions('node', TRUE); $node_view_modes = \Drupal::entityManager()->getViewModes('node'); // Unset unwanted view modes unset($node_view_modes['rss']); unset($node_view_modes['search_index']); unset($node_view_modes['search_result']); // Set a class on the form for the current admin theme, note if this is set to "Default theme" // the result is always 0. $system_theme_config = \Drupal::config('system.theme'); $admin_theme = $system_theme_config->get('admin'); if (!empty($admin_theme)) { $admin_theme_class = 'admin-theme--' . Html::getClass($admin_theme); $form['#attributes'] = array('class' => array($admin_theme_class)); } // Attached required CSS and JS. $form['#attached']['library'][] = 'at_core/at.appearance_settings'; // AT Core if ($theme == 'at_core') { $form['at_core']['message'] = array( '#type' => 'container', '#markup' => t('AT Core has no configuration and cannot be used as a front end theme - it is a base them only. Use the <b>AT Theme Generator</b> to generate or clone a theme to get started.'), ); // Hide form items. $form['theme_settings']['#attributes']['class'] = array('visually-hidden'); $form['logo']['#attributes']['class'] = array('visually-hidden'); $form['favicon']['#attributes']['class'] = array('visually-hidden'); $form['actions']['#attributes']['class'] = array('visually-hidden'); } // AT Subtheme if (isset($getThemeInfo['subtheme type'])) { if ($getThemeInfo['subtheme type'] !== 'adaptive_generator') { // Pass in the generated files path to values and settings. $form['at']['settings_generated_files_path'] = array( '#type' => 'hidden', '#value' => $generated_files_path, ); // Extension settings. require_once($at_core_path . '/forms/ext/extension_settings.php'); // Layouts. require_once($at_core_path . '/forms/layout/layouts.php'); // Basic settings - move into details wrapper and collapse. $form['basic_settings'] = array( '#type' => 'details', '#title' => t('Basic Settings'), '#open' => FALSE, ); $form['theme_settings']['#open'] = FALSE; $form['theme_settings']['#group'] = 'basic_settings'; $form['logo']['#open'] = FALSE; $form['logo']['#group'] = 'basic_settings'; $form['favicon']['#open'] = FALSE; $form['favicon']['#group'] = 'basic_settings'; // buttons don't work with #group, move it the hard way. $form['actions']['#type'] = $form['basic_settings']['actions']['#type'] = 'actions'; $form['actions']['submit']['#type'] = $form['basic_settings']['actions']['submit']['#type'] = 'submit'; $form['actions']['submit']['#value'] = $form['basic_settings']['actions']['submit']['#value'] = t('Save basic settings'); $form['actions']['submit']['#button_type'] = $form['basic_settings']['actions']['submit']['#button_type'] = 'primary'; unset($form['actions']); } } // Modify the color scheme form. if (\Drupal::moduleHandler()->moduleExists('color')) { //include_once($at_core_path . '/forms/color/color_submit.php'); if (isset($build_info['args'][0]) && ($theme = $build_info['args'][0]) && color_get_info($theme) && function_exists('gd_info')) { $form['#process'][] = 'at_core_make_collapsible'; } } }