Below is a differential between the unpatched vulnerable code and the patched update, for reference.
--- a/child-theme-wizard/child-theme-wizard.php
+++ b/child-theme-wizard/child-theme-wizard.php
@@ -1,373 +1,346 @@
-<?php
-/**
- * Plugin Name: Child Theme Wizard
- * Plugin URI: https://wpguru.tv
- * Description: Creates a child theme from any theme you have installed
- * Version: 1.4
- * Author: Jay Versluis
- * Author URI: https://wpguru.tv
- * License: GPL2
- * License URI: http://www.gnu.org/licenses/gpl-2.0.html
- */
-
-/* Copyright 2013-2019 Jay Versluis (email support@wpguru.tv)
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License, version 2, as
- published by the Free Software Foundation.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-*/
-
-// add submenu page under Tools
-function ctw_menu() {
- global $starter_plugin_admin_page;
- $starter_plugin_admin_page = add_submenu_page ('tools.php', __('Child Theme Wizard', 'ctw'), __('Child Theme Wizard', 'ctw'), 'manage_options', 'ChildThemeWizard', 'ctwMainFunction');
-}
-add_action('admin_menu', 'ctw_menu');
-
-
-///////////////////////////////////////////////
-// main function that generates the admin page
-function ctwMainFunction () {
-
-// check that the user has the required capability
- if (!current_user_can('manage_options'))
- {
- wp_die( __('You do not have sufficient privileges to access this page. Sorry!') );
- }
-
- ///////////////////////////////////////
- // MAIN AMDIN CONTENT SECTION
- ///////////////////////////////////////
-
- // display heading with icon WP style
- ?>
- <div class="wrap">
- <div id="icon-index" class="icon32"><br></div>
- <h2>Child Theme Wizard</h2>
-
- <?php
-
- // check if the button has been pressed
- if( isset($_POST[ 'hiddenfield' ]) && $_POST[ 'hiddenfield' ] == 'Y' ) {
-
- // call function with sanitized values
- $newchildtheme = array(
- 'parent' => $_POST['parent'],
- 'title' => sanitize_text_field($_POST['title']),
- 'description' => sanitize_text_field($_POST['description']),
- 'url' => sanitize_text_field($_POST['url']),
- 'author' => sanitize_text_field($_POST['author']),
- 'author-url' => sanitize_text_field($_POST['author-url']),
- 'version' => sanitize_text_field($_POST['version']),
- 'include-gpl' => $_POST['include-gpl'],
- );
-
- // create child theme - let's see if this worked
- $status = ctw_create_theme($newchildtheme);
- // ctw_testing($newchildtheme);
-
- // Put a "settings updated" message on the screen
- if ($status['alert'] == -1) {
- // panic - there was an error
- ?>
- <div class="error">
- <strong><p>Yikes - something went wrong:</p>
- <?php echo $status['message']; ?>
- </strong>
- </div>
- <div><strong><p>Would you like to <a href="<?php get_admin_url('tools.php?page=ChildThemeWizard'); ?>">try again?</a></p></strong></div>
-
- <?php
- } else {
- // everything went fine
- ?>
- <div class="updated">
- <strong>
- <?php echo $status['message']; ?>
- <p>
- <?php _e('Your Child Theme was created successfully!', 'ctw' ); ?>
- </strong></p></div>
- <div>
- <p>Head over to <a href="<?php echo admin_url('themes.php'); ?>">Appearance - Themes</a> to activate it.</p>
- <p>Add your custom styles in <a href="<?php echo admin_url('theme-editor.php'); ?>">Appearance - Editor</a>.</p>
- </div>
- <?php
- }
- } else {
-
- // display the new child theme dialogue
- ?>
-
- <p>This simple wizard will help you generate a new <a href="https://developer.wordpress.org/themes/advanced-topics/child-themes/" target="_blank">Child Theme</a> with just one click. </p>
- <p>Select which theme you want to use as a base, fill in the details and click "Create Child Theme".</p>
- <hr>
- <form name="ctwform" method="post" action="">
- <input type="hidden" name="hiddenfield" value="Y">
-
-
- <?php
-
- // fields for author and title
- // we can pre-populate some data too
- $current_user = wp_get_current_user();
- ?>
- <table width="600" border="0">
- <tr>
- <td>Parent Theme</td>
- <td><?php
- // grab a list of all parent themes and iterate through them
- // $themes = wp_get_themes();
- $themes = ctw_giveme_parents();
- $currentTheme = wp_get_theme();
- echo '<select name="parent">';
- foreach ($themes as $theme) {
- // if it's the current theme, make it selected
- if($currentTheme->get('Name') == $theme->get('Name')) {
- echo '<option value ="' . $theme->get_stylesheet() . '" selected>' . $theme->get('Name') . ' (currently active)</option>';
- } else {
- echo '<option value ="' . $theme->get_stylesheet() . '">' . $theme->get('Name') . '</option>';
- }
- }
- echo '</select>';
- ?></td>
- <td><em></em></td>
- </tr>
- <tr>
- <td>Title</td>
- <td><input type="text" name="title" value="" size="20"></td>
- <td><em>what's your new Child Theme called?</em></td>
- </tr>
- <tr>
- <td>Description</td>
- <td><input type="text" name="description" value="" size="20"></td>
- <td><em>a few notes about your Child Theme</em></td>
- </tr>
- <tr>
- <td>Child Theme URL</td>
- <td><input type="text" name="url" value="" size="20"></td>
- <td><em>does it have a website or release post?</em></td>
- </tr>
- <tr>
- <td>Author</td>
- <td><input type="text" name="author" value="<?php echo $current_user->display_name; ?>" size="20"></td>
- <td><em>that's you</em></td>
- </tr>
- <tr>
- <td>Author URL</td>
- <td><input type="text" name="author-url" value="<?php echo $current_user->user_url; ?>" size="20"></td>
- <td><em>that's your website</em></td>
- </tr>
- <tr>
- <td>Version</td>
- <td><input type="text" name="version" value="1.0" size="20"></td>
- <td><em>start with 1.0 and work your way up</em></td>
- </tr>
- <tr>
- <td>Include GPL License</td>
- <td>
- <select name="include-gpl">
- <option value="on">Yes Please!</option>
- <option value="off">No Thanks</option>
- </select>
- </td>
- <td><em></em></td>
- </tr>
- </table>
-
- <p class="submit">
- <input type="submit" name="Submit" class="button-primary" value="<?php esc_attr_e('Create Child Theme') ?>" />
- </p>
-
- <?php // end of else
- }
- ?>
- <br><hr><br>
-
- </div> <!-- end of main wrap -->
-
-<?php // display the footer ?>
- <p><a href="https://wpguru.co.uk" target="_blank"><img src="<?php
- echo plugins_url('images/guru-header-2013.png', __FILE__); ?>" width="300"></a> </p>
-
-<p><a href="https://wpguru.co.uk/2014/03/introducing-child-theme-wizard-for-wordpress/" target="_blank">Plugin by Jay Versluis</a> | <a href="https://github.com/versluis/Child-Theme-Wizard" target="_blank">Fork me or Contribute on GitHub</a> | <a href="https://patreon.com/versluis" target="_blank">Support me on Patreon</a></p>
-
-<p><span><!-- Social Buttons -->
-
-<!-- YouTube -->
-<script src="https://apis.google.com/js/platform.js"></script>
-<div class="g-ytsubscribe" data-channel="wphosting"></div>
-
-<!-- Place this tag after the last widget tag. -->
-<script type="text/javascript">
- (function() {
- var po = document.createElement('script'); po.type = 'text/javascript'; po.async = true;
- po.src = 'https://apis.google.com/js/platform.js';
- var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(po, s);
- })();
-</script>
-
-
-
-<!-- Twitter -->
-<a href="https://twitter.com/versluis" class="twitter-follow-button" data-show-count="true">Follow @versluis</a>
-<script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0],p=/^http:/.test(d.location)?'http':'https';if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src=p+'://platform.twitter.com/widgets.js';fjs.parentNode.insertBefore(js,fjs);}}(document, 'script', 'twitter-wjs');</script>
-
-<!-- Facebook -->
-<iframe src="//www.facebook.com/plugins/like.php?href=https%3A%2F%2Fwww.facebook.com%2Fpages%2FThe-WP-Guru%2F162188713810370&width&layout=button_count&action=like&show_faces=true&share=true&height=21&appId=186277158097599" scrolling="no" frameborder="0" style="border:none; overflow:hidden; height:21px;" allowTransparency="true"></iframe>
-
-</span></p>
-
-<?php
-} // end of main function
-
-/*
- * this function creates the new directory and file
- */
-
-function ctw_create_theme($childtheme) {
-
- // add messages to this variable
- $status = array();
- $status['alert'] = 0;
-
- // create the directory
- $directory = get_theme_root() . '/' . sanitize_file_name($childtheme['title']);
- // echo '<p>The child theme directory will be created at ' . $directory;
- if (!mkdir($directory)) {
- $status['message'] = "<p>Could not create directory. Does it exist already?</p>";
- $status['alert'] = -1;
- return $status;
- } else {
- $status['message'] = "<p>Directory created successfully.</p>";
- }
-
- // create style.css in our directory
- $filename = $directory . '/' . 'style.css';
- $handle = fopen($filename, 'w');
-
- // add meta data
- $data = "/* n Theme Name: " . $childtheme['title'];
- $data = $data . "n Theme URI: " . $childtheme['url'];
- $data = $data . "n Description: " . $childtheme['description'];
- $data = $data . "n Author: " . $childtheme['author'];
- $data = $data . "n Author URI: " . $childtheme['author-url'];
- $data = $data . "n Template: " . $childtheme['parent'];
- $data = $data . "n Version: " . $childtheme['version'];
-
- // insert GPL License Terms
- if ($childtheme['include-gpl'] == 'on') {
- $data = $data . "n License: GNU General Public License v2 or later";
- $data = $data . "n License URI: http://www.gnu.org/licenses/gpl-2.0.html";
- }
-
- // adding the call to the parent style sheet in CSS is no longer best practice
- // $data = $data . "n*/nn" . '@import url("../' . $childtheme['parent'] . '/style.css");';
- $data = $data . "nn /* == Add your own styles below this line ==";
- $data = $data . "n--------------------------------------------*/nn";
-
- // write data and close the file
- if (fwrite($handle, $data) == false) {
- $status['message'] = $status['message'] . "<p>There was a problem writing data to style.css.</p>";
- $status['alert'] = -1;
- return $status;
- } else {
- $status['message'] = $status['message'] . "<p>Writing data to style.css...</p>";
- }
- fclose($handle);
-
- // create functions.php
- $filename = $directory . '/' . 'functions.php';
- $handle = fopen($filename, 'w');
-
- // add some meta data
- $data = "<?php /*nn This file is part of a child theme called " . $childtheme['title'] . ".";
- $data = $data . "n Functions in this file will be loaded before the parent theme's functions.";
- $data = $data . "n For more information, please read";
- $data = $data . "n https://developer.wordpress.org/themes/advanced-topics/child-themes/";
- $data = $data . "nn*/";
-
- // add call to enqueue parent style sheet via functions.php
- $data = $data . "nn// this code loads the parent's stylesheet (leave it in place unless you know what you're doing)";
- $data = $data . "nnfunction your_theme_enqueue_styles() {";
-
- // @since 1.4: define $parent_style
- $data = $data . "nn " . '$parent_style' . " = 'parent-style';";
-
- $data = $data . "nn wp_enqueue_style( " . '$parent_style' . ", n";
- $data = $data . " get_template_directory_uri() . '/style.css'); n";
-
- $data = $data . "n wp_enqueue_style( 'child-style', n";
- $data = $data . " get_stylesheet_directory_uri() . '/style.css', n";
- $data = $data . " array(". '$parent_style' ."), n";
- $data = $data . " wp_get_theme()->get('Version') n";
- $data = $data . " );n}";
- $data = $data . "nnadd_action('wp_enqueue_scripts', 'your_theme_enqueue_styles');";
-
- $data = $data . "nn/* Add your own functions below this line.";
- $data = $data . "n ======================================== */ nn";
-
- // write data and close the file
- if (fwrite($handle, $data) == false) {
- $status['message'] = $status['message'] . "<p>There was a problem writing data to functions.php.</p>";
- $status['alert'] = -1;
- return $status;
- } else {
- $status['message'] = $status['message'] . "<p>Writing data to functions.php...</p>";
- }
- fclose($handle);
-
- // create a nice screenshot
- $thumbnail_status = ctw_make_thumbnail($directory);
- $status['message'] = $status['message'] . $thumbnail_status;
-
- return $status;
-}
-
-// return an array only of parent themes
-function ctw_giveme_parents() {
-
- // first we'll grab all installed themes
- $allThemes = wp_get_themes();
- $parentThemes = array();
-
- // next we'll add all parents and return the result
- foreach ($allThemes as $theme) {
-
- if ($theme->parent() == false) {
- $parentThemes[] = $theme;
- }
- }
-
- return $parentThemes;
-}
-
-// create a new thumbnail
-function ctw_make_thumbnail($childpath) {
-
- // for now we'll just copy an existing image
- $thumbnail = plugins_url('images/screenshot.png', __FILE__);
- $destination = $childpath . '/screenshot.png';
- if (!copy($thumbnail, $destination)) {
- return "<p>Could not copy thumbnail image :-(</p>";
- } else {
- return "<p>Copied thumbnail file over - looking good!</p>";
- }
-}
-
-// quick tests go here
-function ctw_testing($childtheme) {
-
- $directory = get_theme_root() . '/' . sanitize_file_name($childtheme['title']);
- ctw_make_thumbnail($directory);
-}
-
-?>
+<?php
+/**
+ * Plugin Name: Child Theme Wizard
+ * Plugin URI: https://wpguru.tv
+ * Description: Creates a child theme from any installed parent theme.
+ * Version: 1.5
+ * Author: Jay Versluis
+ * Author URI: https://wpguru.tv
+ * License: GPL2
+ * License URI: http://www.gnu.org/licenses/gpl-2.0.html
+ * Text Domain: child-theme-wizard
+ */
+
+/* Copyright 2013-2026 Jay Versluis (email support@wpguru.tv)
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License, version 2, as
+ published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+if ( ! defined( 'ABSPATH' ) ) {
+ exit;
+}
+
+add_action( 'admin_menu', 'ctw_menu' );
+
+function ctw_menu(): void {
+ add_submenu_page(
+ 'tools.php',
+ __( 'Child Theme Wizard', 'child-theme-wizard' ),
+ __( 'Child Theme Wizard', 'child-theme-wizard' ),
+ 'manage_options',
+ 'ChildThemeWizard',
+ 'ctw_main_function'
+ );
+}
+
+function ctw_main_function(): void {
+
+ if ( ! current_user_can( 'manage_options' ) ) {
+ wp_die( esc_html__( 'You do not have sufficient privileges to access this page.', 'child-theme-wizard' ) );
+ }
+
+ ?>
+ <div class="wrap">
+ <h1><?php esc_html_e( 'Child Theme Wizard', 'child-theme-wizard' ); ?></h1>
+
+ <?php
+
+ if ( isset( $_POST['hiddenfield'] ) && $_POST['hiddenfield'] === 'Y' ) {
+
+ // Verify nonce — blocks CSRF attacks.
+ check_admin_referer( 'ctw_create_child_theme', 'ctw_nonce' );
+
+ // Validate parent against actually-installed parent themes.
+ $parent_themes = ctw_giveme_parents();
+ $valid_parents = array_map( fn( $t ) => $t->get_stylesheet(), $parent_themes );
+ $submitted_parent = sanitize_text_field( wp_unslash( $_POST['parent'] ?? '' ) );
+
+ if ( ! in_array( $submitted_parent, $valid_parents, true ) ) {
+ wp_die( esc_html__( 'Invalid parent theme selected.', 'child-theme-wizard' ) );
+ }
+
+ $newchildtheme = array(
+ 'parent' => $submitted_parent,
+ 'title' => sanitize_text_field( wp_unslash( $_POST['title'] ?? '' ) ),
+ 'description' => sanitize_text_field( wp_unslash( $_POST['description'] ?? '' ) ),
+ 'url' => esc_url_raw( wp_unslash( $_POST['url'] ?? '' ) ),
+ 'author' => sanitize_text_field( wp_unslash( $_POST['author'] ?? '' ) ),
+ 'author-url' => esc_url_raw( wp_unslash( $_POST['author-url'] ?? '' ) ),
+ 'version' => sanitize_text_field( wp_unslash( $_POST['version'] ?? '' ) ),
+ 'include-gpl' => ( isset( $_POST['include-gpl'] ) && $_POST['include-gpl'] === 'on' ) ? 'on' : 'off',
+ );
+
+ $status = ctw_create_theme( $newchildtheme );
+
+ if ( $status['alert'] === -1 ) {
+ ?>
+ <div class="notice notice-error">
+ <p><strong><?php esc_html_e( 'Yikes — something went wrong:', 'child-theme-wizard' ); ?></strong></p>
+ <?php echo wp_kses_post( $status['message'] ); ?>
+ </div>
+ <p><a href="<?php echo esc_url( admin_url( 'tools.php?page=ChildThemeWizard' ) ); ?>"><?php esc_html_e( 'Try again?', 'child-theme-wizard' ); ?></a></p>
+ <?php
+ } else {
+ ?>
+ <div class="notice notice-success">
+ <?php echo wp_kses_post( $status['message'] ); ?>
+ <p><strong><?php esc_html_e( 'Your Child Theme was created successfully!', 'child-theme-wizard' ); ?></strong></p>
+ </div>
+ <p>
+ <?php
+ printf(
+ /* translators: 1: link to Appearance > Themes, 2: link to Appearance > Editor */
+ esc_html__( 'Head over to %1$s to activate it. Add your custom styles in %2$s.', 'child-theme-wizard' ),
+ '<a href="' . esc_url( admin_url( 'themes.php' ) ) . '">' . esc_html__( 'Appearance › Themes', 'child-theme-wizard' ) . '</a>',
+ '<a href="' . esc_url( admin_url( 'theme-editor.php' ) ) . '">' . esc_html__( 'Appearance › Editor', 'child-theme-wizard' ) . '</a>'
+ );
+ ?>
+ </p>
+ <?php
+ }
+ } else {
+
+ $current_user = wp_get_current_user();
+ $parent_themes = ctw_giveme_parents();
+ $current_theme = wp_get_theme();
+ ?>
+
+ <p>
+ <?php
+ printf(
+ /* translators: %s: link to WordPress child theme documentation */
+ esc_html__( 'This simple wizard will help you generate a new %s with just one click.', 'child-theme-wizard' ),
+ '<a href="https://developer.wordpress.org/themes/advanced-topics/child-themes/" target="_blank">' . esc_html__( 'Child Theme', 'child-theme-wizard' ) . '</a>'
+ );
+ ?>
+ </p>
+ <p><?php esc_html_e( 'Select which theme you want to use as a base, fill in the details and click "Create Child Theme".', 'child-theme-wizard' ); ?></p>
+ <hr>
+
+ <form name="ctwform" method="post" action="">
+ <?php wp_nonce_field( 'ctw_create_child_theme', 'ctw_nonce' ); ?>
+ <input type="hidden" name="hiddenfield" value="Y">
+
+ <table class="form-table" role="presentation">
+ <tr>
+ <th scope="row"><label for="ctw-parent"><?php esc_html_e( 'Parent Theme', 'child-theme-wizard' ); ?></label></th>
+ <td>
+ <select name="parent" id="ctw-parent">
+ <?php foreach ( $parent_themes as $theme ) :
+ $stylesheet = $theme->get_stylesheet();
+ $name = $theme->get( 'Name' );
+ $is_active = $current_theme->get( 'Name' ) === $name;
+ ?>
+ <option value="<?php echo esc_attr( $stylesheet ); ?>"<?php selected( $is_active ); ?>>
+ <?php
+ echo esc_html( $name );
+ if ( $is_active ) {
+ echo ' (' . esc_html__( 'currently active', 'child-theme-wizard' ) . ')';
+ }
+ ?>
+ </option>
+ <?php endforeach; ?>
+ </select>
+ </td>
+ </tr>
+ <tr>
+ <th scope="row"><label for="ctw-title"><?php esc_html_e( 'Title', 'child-theme-wizard' ); ?></label></th>
+ <td>
+ <input type="text" name="title" id="ctw-title" value="" class="regular-text">
+ <p class="description"><?php esc_html_e( "What's your new Child Theme called?", 'child-theme-wizard' ); ?></p>
+ </td>
+ </tr>
+ <tr>
+ <th scope="row"><label for="ctw-description"><?php esc_html_e( 'Description', 'child-theme-wizard' ); ?></label></th>
+ <td>
+ <input type="text" name="description" id="ctw-description" value="" class="regular-text">
+ <p class="description"><?php esc_html_e( 'A few notes about your Child Theme.', 'child-theme-wizard' ); ?></p>
+ </td>
+ </tr>
+ <tr>
+ <th scope="row"><label for="ctw-url"><?php esc_html_e( 'Child Theme URL', 'child-theme-wizard' ); ?></label></th>
+ <td>
+ <input type="url" name="url" id="ctw-url" value="" class="regular-text">
+ <p class="description"><?php esc_html_e( 'Does it have a website or release post?', 'child-theme-wizard' ); ?></p>
+ </td>
+ </tr>
+ <tr>
+ <th scope="row"><label for="ctw-author"><?php esc_html_e( 'Author', 'child-theme-wizard' ); ?></label></th>
+ <td>
+ <input type="text" name="author" id="ctw-author" value="<?php echo esc_attr( $current_user->display_name ); ?>" class="regular-text">
+ <p class="description"><?php esc_html_e( "That's you.", 'child-theme-wizard' ); ?></p>
+ </td>
+ </tr>
+ <tr>
+ <th scope="row"><label for="ctw-author-url"><?php esc_html_e( 'Author URL', 'child-theme-wizard' ); ?></label></th>
+ <td>
+ <input type="url" name="author-url" id="ctw-author-url" value="<?php echo esc_url( $current_user->user_url ); ?>" class="regular-text">
+ <p class="description"><?php esc_html_e( "That's your website.", 'child-theme-wizard' ); ?></p>
+ </td>
+ </tr>
+ <tr>
+ <th scope="row"><label for="ctw-version"><?php esc_html_e( 'Version', 'child-theme-wizard' ); ?></label></th>
+ <td>
+ <input type="text" name="version" id="ctw-version" value="1.0" class="small-text">
+ <p class="description"><?php esc_html_e( 'Start with 1.0 and work your way up.', 'child-theme-wizard' ); ?></p>
+ </td>
+ </tr>
+ <tr>
+ <th scope="row"><label for="ctw-include-gpl"><?php esc_html_e( 'Include GPL License', 'child-theme-wizard' ); ?></label></th>
+ <td>
+ <select name="include-gpl" id="ctw-include-gpl">
+ <option value="on"><?php esc_html_e( 'Yes Please!', 'child-theme-wizard' ); ?></option>
+ <option value="off"><?php esc_html_e( 'No Thanks', 'child-theme-wizard' ); ?></option>
+ </select>
+ </td>
+ </tr>
+ </table>
+
+ <p class="submit">
+ <input type="submit" name="Submit" class="button-primary" value="<?php esc_attr_e( 'Create Child Theme', 'child-theme-wizard' ); ?>">
+ </p>
+ </form>
+
+ <?php
+ }
+ ?>
+
+ <br><hr><br>
+ </div><!-- .wrap -->
+
+ <p><a href="https://wpguru.co.uk" target="_blank"><img src="<?php echo esc_url( plugins_url( 'images/guru-header-2013.png', __FILE__ ) ); ?>" width="300" alt="WP Guru"></a></p>
+
+ <p>
+ <a href="https://wpguru.co.uk/2014/03/introducing-child-theme-wizard-for-wordpress/" target="_blank">Plugin by Jay Versluis</a>
+ | <a href="https://github.com/versluis/Child-Theme-Wizard" target="_blank">Fork me or Contribute on GitHub</a>
+ | <a href="https://patreon.com/versluis" target="_blank">Support me on Patreon</a>
+ </p>
+
+ <?php
+}
+
+function ctw_create_theme( array $childtheme ): array {
+
+ $status = array(
+ 'alert' => 0,
+ 'message' => '',
+ );
+
+ global $wp_filesystem;
+ if ( empty( $wp_filesystem ) ) {
+ require_once ABSPATH . 'wp-admin/includes/file.php';
+ WP_Filesystem();
+ }
+
+ $directory = get_theme_root() . '/' . sanitize_file_name( $childtheme['title'] );
+
+ if ( ! $wp_filesystem->mkdir( $directory ) ) {
+ $status['message'] = '<p>' . esc_html__( 'Could not create directory. Does it exist already?', 'child-theme-wizard' ) . '</p>';
+ $status['alert'] = -1;
+ return $status;
+ }
+
+ $status['message'] .= '<p>' . esc_html__( 'Directory created successfully.', 'child-theme-wizard' ) . '</p>';
+
+ // Strip */ so user-supplied values cannot break out of the CSS comment block.
+ $safe = array_map( fn( $v ) => str_replace( '*/', '', (string) $v ), $childtheme );
+
+ $style = "/* n Theme Name: " . $safe['title'];
+ $style .= "n Theme URI: " . $safe['url'];
+ $style .= "n Description: " . $safe['description'];
+ $style .= "n Author: " . $safe['author'];
+ $style .= "n Author URI: " . $safe['author-url'];
+ $style .= "n Template: " . $safe['parent'];
+ $style .= "n Version: " . $safe['version'];
+
+ if ( $safe['include-gpl'] === 'on' ) {
+ $style .= "n License: GNU General Public License v2 or later";
+ $style .= "n License URI: http://www.gnu.org/licenses/gpl-2.0.html";
+ }
+
+ $style .= "nn /* == Add your own styles below this line ==";
+ $style .= "n--------------------------------------------*/nn";
+
+ if ( ! $wp_filesystem->put_contents( $directory . '/style.css', $style, FS_CHMOD_FILE ) ) {
+ $status['message'] .= '<p>' . esc_html__( 'There was a problem writing data to style.css.', 'child-theme-wizard' ) . '</p>';
+ $status['alert'] = -1;
+ return $status;
+ }
+
+ $status['message'] .= '<p>' . esc_html__( 'Writing data to style.css…', 'child-theme-wizard' ) . '</p>';
+
+ $functions = "<?phpn/*nn This file is part of a child theme called " . $safe['title'] . ".";
+ $functions .= "n Functions in this file will be loaded before the parent theme's functions.";
+ $functions .= "n For more information, please read";
+ $functions .= "n https://developer.wordpress.org/themes/advanced-topics/child-themes/";
+ $functions .= "nn*/nn";
+ $functions .= "// Loads the parent stylesheet — leave this in place unless you know what you're doing.n";
+ $functions .= "function your_theme_enqueue_styles() {nn";
+ $functions .= " $parent_style = 'parent-style';nn";
+ $functions .= " wp_enqueue_style( $parent_style,n";
+ $functions .= " get_template_directory_uri() . '/style.css'n";
+ $functions .= " );nn";
+ $functions .= " wp_enqueue_style( 'child-style',n";
+ $functions .= " get_stylesheet_directory_uri() . '/style.css',n";
+ $functions .= " array( $parent_style ),n";
+ $functions .= " wp_get_theme()->get( 'Version' )n";
+ $functions .= " );n";
+ $functions .= "}n";
+ $functions .= "add_action( 'wp_enqueue_scripts', 'your_theme_enqueue_styles' );nn";
+ $functions .= "/* Add your own functions below this line.n";
+ $functions .= " ======================================== */nn";
+
+ if ( ! $wp_filesystem->put_contents( $directory . '/functions.php', $functions, FS_CHMOD_FILE ) ) {
+ $status['message'] .= '<p>' . esc_html__( 'There was a problem writing data to functions.php.', 'child-theme-wizard' ) . '</p>';
+ $status['alert'] = -1;
+ return $status;
+ }
+
+ $status['message'] .= '<p>' . esc_html__( 'Writing data to functions.php…', 'child-theme-wizard' ) . '</p>';
+
+ $status['message'] .= ctw_make_thumbnail( $directory );
+
+ return $status;
+}
+
+function ctw_giveme_parents(): array {
+
+ $parent_themes = array();
+
+ foreach ( wp_get_themes() as $theme ) {
+ if ( $theme->parent() === false ) {
+ $parent_themes[] = $theme;
+ }
+ }
+
+ return $parent_themes;
+}
+
+function ctw_make_thumbnail( string $childpath ): string {
+
+ global $wp_filesystem;
+ if ( empty( $wp_filesystem ) ) {
+ require_once ABSPATH . 'wp-admin/includes/file.php';
+ WP_Filesystem();
+ }
+
+ $source = plugin_dir_path( __FILE__ ) . 'images/screenshot.png';
+ $destination = $childpath . '/screenshot.png';
+
+ if ( ! $wp_filesystem->copy( $source, $destination ) ) {
+ return '<p>' . esc_html__( 'Could not copy thumbnail image.', 'child-theme-wizard' ) . '</p>';
+ }
+
+ return '<p>' . esc_html__( 'Copied thumbnail file — looking good!', 'child-theme-wizard' ) . '</p>';
+}
--- a/child-theme-wizard/uninstall.php
+++ b/child-theme-wizard/uninstall.php
@@ -1,29 +1,7 @@
<?php
-// Child Theme Wizard uninstall script
-// deletes all database options when plugin is removed
-// @since 1.0
-//
-// Direct calls to this file are Forbidden when core files are not present
-// Thanks to Ed from ait-pro.com for this code
-
-if ( !function_exists('add_action') ){
-header('Status: 403 Forbidden');
-header('HTTP/1.1 403 Forbidden');
-exit();
-}
-
-if ( !current_user_can('manage_options') ){
-header('Status: 403 Forbidden');
-header('HTTP/1.1 403 Forbidden');
-exit();
+// Direct file access guard must come first.
+if ( ! defined( 'WP_UNINSTALL_PLUGIN' ) ) {
+ exit;
}
-// if uninstall is not called from WordPress then exit
-if (!defined('WP_UNINSTALL_PLUGIN')) exit();
-
-// this plugin does not add any options to the database
-// if it would, they would be removed here
-
-// Thanks for using this plugin
-// If you'd like to try again someday check out http://wpguru.co.uk where it lives and grows
-?>
No newline at end of file
+// This plugin stores no options in the database, so there is nothing to clean up.