Child Themify - Version 1.0.2

Version Description

  • Added support for WP 3.8
Download this release

Release Info

Developer JohnPBloch
Plugin Icon wp plugin Child Themify
Version 1.0.2
Comparing to
See all releases

Code changes from version 1.0.1 to 1.0.2

assets/js/child-themify.js ADDED
@@ -0,0 +1,78 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ (function (window, l10n, undefined) {
2
+ var $ = window.jQuery,
3
+ themes = window.wp.themes,
4
+ themesView,
5
+ themeViews = {};
6
+
7
+ function createUrl(theme) {
8
+ var link = window.location.href;
9
+ if (link.indexOf('?')) {
10
+ link = link.substr(0, link.indexOf('?'));
11
+ }
12
+ link += '?action=child-themify';
13
+ link += '&theme=' + theme;
14
+ link += '&_ctf_nonce=' + l10n.nonce;
15
+
16
+ return link;
17
+ }
18
+
19
+ function injectLinks(into, model) {
20
+ if (model.get('parent')) {
21
+ return;
22
+ }
23
+ var className = '.theme-actions .' + (model.get('active') ? '' : 'in') + 'active-theme',
24
+ links = into.find(className),
25
+ link = createUrl(model.id);
26
+ if (links.length) {
27
+ links.first().append('<a href="' + link + '" class="button button-secondary">' +
28
+ l10n.createAChildTheme +
29
+ '</a>');
30
+ }
31
+ }
32
+
33
+ function onExpand() {
34
+ window.setTimeout(function () {
35
+ injectLinks(themesView.overlay.$el, themesView.model);
36
+ }, 30);
37
+ }
38
+
39
+ function initialize() {
40
+ var index,
41
+ obj,
42
+ listeners = themesView._listeners,
43
+ count = 0;
44
+ for (index in listeners) {
45
+ if (listeners.hasOwnProperty(index)) {
46
+ obj = listeners[index];
47
+ if (obj instanceof themes.view.Theme) {
48
+ themeViews[obj.model.id] = obj;
49
+ count += 1;
50
+ }
51
+ }
52
+ }
53
+
54
+ if (count === 1) {
55
+ injectLinks(themesView.singleTheme.$el, themesView.model);
56
+ } else if (count > 0) {
57
+ for (index in themeViews) {
58
+ if (themeViews.hasOwnProperty(index)) {
59
+ themesView.listenTo(themeViews[index], 'theme:expand', onExpand);
60
+ }
61
+ }
62
+ }
63
+ }
64
+
65
+ function onLoad() {
66
+ themesView = themes.Run.view.view;
67
+
68
+ initialize();
69
+
70
+ if (undefined !== themes.data.settings.theme && '' !== themes.data.settings.theme) {
71
+ injectLinks(themesView.overlay.$el, themesView.model);
72
+ }
73
+
74
+ themesView.listenTo(themesView.collection, 'update', initialize);
75
+ }
76
+
77
+ $(onLoad);
78
+ }(window, window.childThemify));
assets/js/child-themify.min.js ADDED
@@ -0,0 +1,2 @@
 
 
1
+ /*! Child Themify - v1.0.2
2
+ * Copyright (c) 2014 John P. Bloch */!function(a,b,c){function d(c){var d=a.location.href;return d.indexOf("?")&&(d=d.substr(0,d.indexOf("?"))),d+="?action=child-themify",d+="&theme="+c,d+="&_ctf_nonce="+b.nonce}function e(a,c){if(!c.get("parent")){var e=".theme-actions ."+(c.get("active")?"":"in")+"active-theme",f=a.find(e),g=d(c.id);f.length&&f.first().append('<a href="'+g+'" class="button button-secondary">'+b.createAChildTheme+"</a>")}}function f(){a.setTimeout(function(){e(i.overlay.$el,i.model)},30)}function g(){var a,b,c=i._listeners,d=0;for(a in c)c.hasOwnProperty(a)&&(b=c[a],b instanceof k.view.Theme&&(l[b.model.id]=b,d+=1));if(1===d)e(i.singleTheme.$el,i.model);else if(d>0)for(a in l)l.hasOwnProperty(a)&&i.listenTo(l[a],"theme:expand",f)}function h(){i=k.Run.view.view,g(),c!==k.data.settings.theme&&""!==k.data.settings.theme&&e(i.overlay.$el,i.model),i.listenTo(i.collection,"update",g)}var i,j=a.jQuery,k=a.wp.themes,l={};j(h)}(window,window.childThemify);
assets/js/legacy.js ADDED
@@ -0,0 +1,31 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ (function (window, l10n) {
2
+ if (typeof l10n.link !== 'string' || l10n.link.length < 1) {
3
+ return;
4
+ }
5
+ var document = window.document,
6
+ themeOptions = document.getElementById('customize-current-theme-link'),
7
+ x,
8
+ optionsLinks,
9
+ newListItem,
10
+ newLink;
11
+ if (themeOptions) {
12
+ themeOptions = themeOptions.parentNode;
13
+ } else {
14
+ return;
15
+ }
16
+ for (x in themeOptions.childNodes) {
17
+ if (themeOptions.childNodes.hasOwnProperty(x) && themeOptions.childNodes[x].nodeName !== undefined && themeOptions.childNodes[x].nodeName.toUpperCase() === 'UL') {
18
+ optionsLinks = themeOptions.childNodes[x];
19
+ break;
20
+ }
21
+ }
22
+ if (!optionsLinks) {
23
+ return;
24
+ }
25
+ newLink = document.createElement('a');
26
+ newLink.appendChild(document.createTextNode(l10n.createAChildTheme));
27
+ newLink.href = l10n.link;
28
+ newListItem = document.createElement('li');
29
+ newListItem.appendChild(newLink);
30
+ optionsLinks.appendChild(newListItem);
31
+ }(window, window.childThemify));
assets/js/legacy.min.js ADDED
@@ -0,0 +1,2 @@
 
 
1
+ /*! Child Themify - v1.0.2
2
+ * Copyright (c) 2014 John P. Bloch */!function(a,b){if(!("string"!=typeof b.link||b.link.length<1)){var c,d,e,f,g=a.document,h=g.getElementById("customize-current-theme-link");if(h){h=h.parentNode;for(c in h.childNodes)if(h.childNodes.hasOwnProperty(c)&&void 0!==h.childNodes[c].nodeName&&"UL"===h.childNodes[c].nodeName.toUpperCase()){d=h.childNodes[c];break}d&&(f=g.createElement("a"),f.appendChild(g.createTextNode(b.createAChildTheme)),f.href=b.link,e=g.createElement("li"),e.appendChild(f),d.appendChild(e))}}}(window,window.childThemify);
child-themify.php CHANGED
@@ -2,184 +2,27 @@
2
  /*
3
  * Plugin Name: Child Themify
4
  * Description: Enables the quick creation of child themes from any non-child theme you have installed.
5
- * Version: 1.0.1
6
  * Plugin URI: https://github.com/johnpbloch/child-themify
7
  * Author: John P. Bloch
8
  * License: GPLv2 or later
9
  */
10
 
11
- class CTF_Babymaker {
 
 
12
 
13
- /**
14
- * Check the user's capabilities and validate the nonce
15
- *
16
- * Kills script execution if either of those tests fail
17
- */
18
- public static function getTested() {
19
- $theme = empty( $_GET['theme'] ) ? '' : $_GET['theme'];
20
- if ( !self::fertile() ) {
21
- wp_die( __( 'You do not have permission to do that!', 'child-themify' ) );
22
- }
23
- check_admin_referer( self::nonce_name( $theme ), '_ctf_nonce' );
24
- }
25
-
26
- protected static function fertile() {
27
- return current_user_can( 'install_themes' );
28
- }
29
-
30
- protected static function nonce( $theme ) {
31
- return wp_create_nonce( self::nonce_name( $theme ) );
32
- }
33
-
34
- protected static function nonce_name( $theme ) {
35
- return "child_themify_$theme";
36
- }
37
-
38
- public static function showInterface() {
39
- $theme = empty( $_GET['theme'] ) ? '' : $_GET['theme'];
40
- $theme = wp_get_theme( $theme );
41
- if ( self::checkCreds() ) {
42
- return;
43
- }
44
- settings_errors();
45
- ?>
46
- <div class="wrap">
47
- <h2><?php echo esc_html( sprintf( _x( 'Create a child theme from %s', 'The placeholder is for a theme\'s name', 'child-themify' ), $theme->name ) ); ?></h2>
48
- <form method="post" action="<?php echo esc_url( self::getLink( $theme->get_stylesheet() ) ); ?>">
49
- <label><?php esc_html_e( 'Name your child theme', 'child-themify' ); ?></label><br>
50
- <input type="text" name="new_theme" />
51
- <?php submit_button( __( "Let's go!", 'child-themify' ) ); ?>
52
- </form>
53
- </div>
54
- <?php
55
- }
56
-
57
- protected static function checkCreds() {
58
- if ( empty( $_POST ) ) {
59
- return false;
60
- }
61
- self::getTested();
62
- $theme = empty( $_GET['theme'] ) ? '' : $_GET['theme'];
63
- $theme = wp_get_theme( $theme );
64
- $url = self::getLink( $theme );
65
- if ( ($creds = request_filesystem_credentials( $url, '', false, get_theme_root(), array( 'new_theme' ) )) === false ) {
66
- return true;
67
- }
68
- if ( !WP_Filesystem( $creds, get_theme_root() ) ) {
69
- request_filesystem_credentials( $url, '', true, get_theme_root(), array( 'new_theme' ) );
70
- return true;
71
- }
72
- self::procreate( $_POST['new_theme'], $theme );
73
- }
74
-
75
- /**
76
- * Get the link to create a child theme from a theme
77
- *
78
- * @param string $theme_name The template theme's directory
79
- * @return string The url to create a child theme
80
- */
81
- public static function getLink( $theme_name ) {
82
- $theme = wp_get_theme( $theme_name );
83
- // If the current user can't install a theme, the theme doesn't exist
84
- if ( !self::fertile() || !$theme->exists() || $theme->parent() ) {
85
- return '';
86
- }
87
- $args = array(
88
- 'action' => 'child-themify',
89
- 'theme' => $theme_name,
90
- '_ctf_nonce' => self::nonce( $theme_name ),
91
- );
92
- $baseLink = is_multisite() ? network_admin_url( 'themes.php' ) : admin_url( 'themes.php' );
93
- return add_query_arg( $args, $baseLink );
94
- }
95
 
96
- /**
97
- * Add the link for creating a child theme to the theme action links
98
- *
99
- * @param array $links
100
- * @param string|WP_Theme $theme
101
- * @return array An array of action links
102
- */
103
- public static function moodLighting( array $links, $theme ) {
104
- if ( !($theme instanceof WP_Theme) ) {
105
- $theme = wp_get_theme( $theme );
106
- }
107
- if ( !self::fertile() || !$theme->exists() || $theme->parent() ) {
108
- return $links;
109
- }
110
- $link = self::getLink( $theme->get_stylesheet() );
111
- $html = sprintf( "<a href=\"$link\">%s</a>", __( 'Create a child theme', 'child-themify' ) );
112
- $links['child-themify'] = $html;
113
- return $links;
114
  }
115
-
116
- /**
117
- * Runs the actual child theme creation functionality
118
- *
119
- * @global WP_Filesystem_Base $wp_filesystem
120
- * @param string $new_theme
121
- * @param WP_Theme $template
122
- * @throws Exception If the global filesystem object isn't available
123
- */
124
- public static function procreate( $new_theme, WP_Theme $template ) {
125
- global $wp_filesystem;
126
- if ( !($wp_filesystem instanceof WP_Filesystem_Base) ) {
127
- if ( !WP_Filesystem() ) {
128
- throw new Exception( __( 'Could not access the filesystem!', 'child-themify' ) );
129
- }
130
- }
131
- $oldStylesheet = $template->get_stylesheet();
132
- $oldName = $template->name;
133
- $new_theme_directory = trailingslashit( get_theme_root() ) . sanitize_file_name( strtolower( $new_theme ) );
134
- $wp_filesystem->mkdir( $new_theme_directory );
135
- $newStylesheet = trailingslashit( $new_theme_directory ) . 'style.css';
136
- $wp_filesystem->touch( $newStylesheet );
137
- $stylesheetContents = <<<EOF
138
- /*
139
- Theme Name: $new_theme
140
- Version: 1.0
141
- Description: A child theme of $oldName
142
- Template: $oldStylesheet
143
- */
144
-
145
- @import url("../$oldStylesheet/style.css");
146
-
147
- EOF;
148
- $wp_filesystem->put_contents( $newStylesheet, $stylesheetContents );
149
- add_settings_error( '', 'child-themify', __( 'Your child theme was created successfully.', 'child-themify' ), 'updated' );
150
- }
151
-
152
- public static function load_themes_page() {
153
- if ( empty( $_GET['action'] ) || $_GET['action'] != 'child-themify' ) {
154
- if ( !is_multisite() ) {
155
- add_action( 'admin_footer', array( 'CTF_Babymaker', 'link_current_theme') );
156
- }
157
- return;
158
- }
159
- require ABSPATH . 'wp-admin/admin-header.php';
160
- self::showInterface();
161
- require ABSPATH . 'wp-admin/admin-footer.php';
162
- exit;
163
- }
164
-
165
- public static function link_current_theme() {
166
- $theme = wp_get_theme();
167
- $link = self::getLink( $theme->get_stylesheet() );
168
- $filename = defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ? 'ctf.js' : 'ctf.min.js';
169
- wp_enqueue_script( 'child-themify', plugins_url( $filename, __FILE__ ), array(), '1.0', true );
170
- wp_localize_script( 'child-themify', 'childThemify', array(
171
- 'createAChildTheme' => __( 'Create a child theme', 'child-themify' ),
172
- 'link' => $link,
173
- ));
174
- }
175
-
176
- public static function init() {
177
- load_plugin_textdomain( 'child-themify', false, basename( dirname( __FILE__ ) ) . '/languages' );
178
- add_filter( 'theme_action_links', array( 'CTF_Babymaker', 'moodLighting' ), 10, 2 );
179
- add_action( 'load-themes.php', array( 'CTF_Babymaker', 'load_themes_page' ) );
180
- }
181
-
182
  }
183
 
184
- add_action( 'init', array( 'CTF_Babymaker', 'init' ) );
185
-
2
  /*
3
  * Plugin Name: Child Themify
4
  * Description: Enables the quick creation of child themes from any non-child theme you have installed.
5
+ * Version: 1.0.2
6
  * Plugin URI: https://github.com/johnpbloch/child-themify
7
  * Author: John P. Bloch
8
  * License: GPLv2 or later
9
  */
10
 
11
+ define( 'CTF_PATH', WP_PLUGIN_DIR . '/' . basename( dirname( __FILE__ ) ) . '/' . basename( __FILE__ ) );
12
+ define( 'CTF_URL', WP_PLUGIN_URL . '/' . basename( dirname( __FILE__ ) ) . '/' . basename( __FILE__ ) );
13
+ define( 'CTF_VERSION', '1.0.2' );
14
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
15
 
16
+ function ctf_plugins_loaded() {
17
+ if ( version_compare( $GLOBALS['wp_version'], '3.8', '>=' ) ) {
18
+ global $child_themify;
19
+ require_once dirname( CTF_PATH ) . '/includes/plugin.php';
20
+ $child_themify = new Child_Themify();
21
+ add_action( 'init', array( $child_themify, 'init' ) );
22
+ } else {
23
+ require_once dirname( CTF_PATH ) . '/includes/legacy.php';
24
+ add_action( 'init', array( 'CTF_Babymaker', 'init' ) );
 
 
 
 
 
 
 
 
 
25
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
26
  }
27
 
28
+ add_action( 'plugins_loaded', 'ctf_plugins_loaded' );
 
ctf.js DELETED
@@ -1,32 +0,0 @@
1
- (function(l10n){
2
- if ( typeof l10n.link !== 'string' || l10n.link.length < 1 ) {
3
- return;
4
- }
5
- var themeOptions = document.getElementById('customize-current-theme-link'),
6
- x,
7
- optionsLinks,
8
- newListItem,
9
- newLink;
10
- if ( themeOptions ) {
11
- themeOptions = themeOptions.parentNode;
12
- } else {
13
- return;
14
- }
15
- for( x in themeOptions.childNodes ) {
16
- if ( themeOptions.childNodes[x].nodeName !== undefined ) {
17
- if ( themeOptions.childNodes[x].nodeName.toUpperCase() === 'UL' ) {
18
- optionsLinks = themeOptions.childNodes[x];
19
- break;
20
- }
21
- }
22
- }
23
- if ( !optionsLinks ) {
24
- return;
25
- }
26
- newLink = document.createElement( 'a' );
27
- newLink.appendChild( document.createTextNode( l10n.createAChildTheme ) );
28
- newLink.href = l10n.link;
29
- newListItem = document.createElement( 'li' );
30
- newListItem.appendChild( newLink );
31
- optionsLinks.appendChild( newListItem );
32
- }(childThemify));
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
ctf.min.js DELETED
@@ -1 +0,0 @@
1
- (function(e){if(typeof e.link!="string"||e.link.length<1)return;var t=document.getElementById("customize-current-theme-link"),n,r,i,s;if(!t)return;t=t.parentNode;for(n in t.childNodes)if(t.childNodes[n].nodeName!==undefined&&t.childNodes[n].nodeName.toUpperCase()==="UL"){r=t.childNodes[n];break}if(!r)return;s=document.createElement("a"),s.appendChild(document.createTextNode(e.createAChildTheme)),s.href=e.link,i=document.createElement("li"),i.appendChild(s),r.appendChild(i)})(childThemify);
 
includes/legacy.php ADDED
@@ -0,0 +1,181 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class CTF_Babymaker {
4
+
5
+ /**
6
+ * Check the user's capabilities and validate the nonce
7
+ *
8
+ * Kills script execution if either of those tests fail
9
+ */
10
+ public static function getTested() {
11
+ $theme = empty( $_GET['theme'] ) ? '' : $_GET['theme'];
12
+ if ( ! self::fertile() ) {
13
+ wp_die( __( 'You do not have permission to do that!', 'child-themify' ) );
14
+ }
15
+ check_admin_referer( self::nonce_name( $theme ), '_ctf_nonce' );
16
+ }
17
+
18
+ protected static function fertile() {
19
+ return current_user_can( 'install_themes' );
20
+ }
21
+
22
+ protected static function nonce( $theme ) {
23
+ return wp_create_nonce( self::nonce_name( $theme ) );
24
+ }
25
+
26
+ protected static function nonce_name( $theme ) {
27
+ return "child_themify_$theme";
28
+ }
29
+
30
+ public static function showInterface() {
31
+ $theme = empty( $_GET['theme'] ) ? '' : $_GET['theme'];
32
+ $theme = wp_get_theme( $theme );
33
+ if ( self::checkCreds() ) {
34
+ return;
35
+ }
36
+ settings_errors();
37
+ ?>
38
+ <div class="wrap">
39
+ <h2><?php echo esc_html( sprintf( _x( 'Create a child theme from %s', 'The placeholder is for a theme\'s name', 'child-themify' ), $theme->name ) ); ?></h2>
40
+
41
+ <form method="post" action="<?php echo esc_url( self::getLink( $theme->get_stylesheet() ) ); ?>">
42
+ <label><?php esc_html_e( 'Name your child theme', 'child-themify' ); ?></label><br>
43
+ <input type="text" name="new_theme" />
44
+ <?php submit_button( __( "Let's go!", 'child-themify' ) ); ?>
45
+ </form>
46
+ </div>
47
+ <?php
48
+ }
49
+
50
+ protected static function checkCreds() {
51
+ if ( empty( $_POST ) ) {
52
+ return false;
53
+ }
54
+ self::getTested();
55
+ $theme = empty( $_GET['theme'] ) ? '' : $_GET['theme'];
56
+ $theme = wp_get_theme( $theme );
57
+ $url = self::getLink( $theme );
58
+ if ( ( $creds = request_filesystem_credentials( $url, '', false, get_theme_root(), array( 'new_theme' ) ) ) === false ) {
59
+ return true;
60
+ }
61
+ if ( ! WP_Filesystem( $creds, get_theme_root() ) ) {
62
+ request_filesystem_credentials( $url, '', true, get_theme_root(), array( 'new_theme' ) );
63
+ return true;
64
+ }
65
+ self::procreate( $_POST['new_theme'], $theme );
66
+ }
67
+
68
+ /**
69
+ * Get the link to create a child theme from a theme
70
+ *
71
+ * @param string $theme_name The template theme's directory
72
+ *
73
+ * @return string The url to create a child theme
74
+ */
75
+ public static function getLink( $theme_name ) {
76
+ $theme = wp_get_theme( $theme_name );
77
+ // If the current user can't install a theme, the theme doesn't exist
78
+ if ( ! self::fertile() || ! $theme->exists() || $theme->parent() ) {
79
+ return '';
80
+ }
81
+ $args = array(
82
+ 'action' => 'child-themify',
83
+ 'theme' => $theme_name,
84
+ '_ctf_nonce' => self::nonce( $theme_name ),
85
+ );
86
+ $baseLink = is_multisite() ? network_admin_url( 'themes.php' ) : admin_url( 'themes.php' );
87
+ return add_query_arg( $args, $baseLink );
88
+ }
89
+
90
+ /**
91
+ * Add the link for creating a child theme to the theme action links
92
+ *
93
+ * @param array $links
94
+ * @param string|WP_Theme $theme
95
+ *
96
+ * @return array An array of action links
97
+ */
98
+ public static function moodLighting( array $links, $theme ) {
99
+ if ( ! ( $theme instanceof WP_Theme ) ) {
100
+ $theme = wp_get_theme( $theme );
101
+ }
102
+ if ( ! self::fertile() || ! $theme->exists() || $theme->parent() ) {
103
+ return $links;
104
+ }
105
+ $link = self::getLink( $theme->get_stylesheet() );
106
+ $html = sprintf( "<a href=\"$link\">%s</a>", __( 'Create a child theme', 'child-themify' ) );
107
+ $links['child-themify'] = $html;
108
+ return $links;
109
+ }
110
+
111
+ /**
112
+ * Runs the actual child theme creation functionality
113
+ *
114
+ * @global WP_Filesystem_Base $wp_filesystem
115
+ *
116
+ * @param string $new_theme
117
+ * @param WP_Theme $template
118
+ *
119
+ * @throws Exception If the global filesystem object isn't available
120
+ */
121
+ public static function procreate( $new_theme, WP_Theme $template ) {
122
+ global $wp_filesystem;
123
+ if ( ! ( $wp_filesystem instanceof WP_Filesystem_Base ) ) {
124
+ if ( ! WP_Filesystem() ) {
125
+ throw new Exception( __( 'Could not access the filesystem!', 'child-themify' ) );
126
+ }
127
+ }
128
+ $oldStylesheet = $template->get_stylesheet();
129
+ $oldName = $template->name;
130
+ $new_theme_directory = trailingslashit( get_theme_root() ) . sanitize_file_name( strtolower( $new_theme ) );
131
+ $wp_filesystem->mkdir( $new_theme_directory );
132
+ $newStylesheet = trailingslashit( $new_theme_directory ) . 'style.css';
133
+ $wp_filesystem->touch( $newStylesheet );
134
+ $stylesheetContents = <<<EOF
135
+ /*
136
+ Theme Name: $new_theme
137
+ Version: 1.0
138
+ Description: A child theme of $oldName
139
+ Template: $oldStylesheet
140
+ */
141
+
142
+ @import url("../$oldStylesheet/style.css");
143
+
144
+ EOF;
145
+ $wp_filesystem->put_contents( $newStylesheet, $stylesheetContents );
146
+ add_settings_error( '', 'child-themify', __( 'Your child theme was created successfully.', 'child-themify' ), 'updated' );
147
+ }
148
+
149
+ public static function load_themes_page() {
150
+ if ( empty( $_GET['action'] ) || $_GET['action'] != 'child-themify' ) {
151
+ if ( ! is_multisite() ) {
152
+ add_action( 'admin_footer', array( 'CTF_Babymaker', 'link_current_theme' ) );
153
+ }
154
+ return;
155
+ }
156
+ require ABSPATH . 'wp-admin/admin-header.php';
157
+ self::showInterface();
158
+ require ABSPATH . 'wp-admin/admin-footer.php';
159
+ exit;
160
+ }
161
+
162
+ public static function link_current_theme() {
163
+ $theme = wp_get_theme();
164
+ $link = self::getLink( $theme->get_stylesheet() );
165
+ $filename = 'assets/js/legacy.';
166
+ $filename .= defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ? 'js' : 'min.js';
167
+ wp_enqueue_script( 'child-themify', plugins_url( $filename, CTF_PATH ), array(), '1.0', true );
168
+ wp_localize_script( 'child-themify', 'childThemify', array(
169
+ 'createAChildTheme' => __( 'Create a child theme', 'child-themify' ),
170
+ 'link' => $link,
171
+ ) );
172
+ }
173
+
174
+ public static function init() {
175
+ load_plugin_textdomain( 'child-themify', false, basename( dirname( CTF_PATH ) ) . '/languages' );
176
+ add_filter( 'theme_action_links', array( 'CTF_Babymaker', 'moodLighting' ), 10, 2 );
177
+ add_action( 'load-themes.php', array( 'CTF_Babymaker', 'load_themes_page' ) );
178
+ }
179
+
180
+ }
181
+
includes/plugin.php ADDED
@@ -0,0 +1,230 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ class Child_Themify {
4
+
5
+ /**
6
+ * Check the user's capabilities and validate the nonce
7
+ *
8
+ * Kills script execution if either of those tests fail
9
+ *
10
+ * @param WP_Theme $theme
11
+ */
12
+ public function isActionAllowed( WP_Theme $theme ) {
13
+ if ( ! $this->checkCapability() ) {
14
+ wp_die( __( 'You do not have permission to do that!', 'child-themify' ) );
15
+ }
16
+ check_admin_referer( $this->nonceName( $theme ), '_ctf_nonce' );
17
+ }
18
+
19
+ public function checkCapability() {
20
+ return current_user_can( 'install_themes' );
21
+ }
22
+
23
+ /**
24
+ * @param WP_Theme $theme
25
+ *
26
+ * @return bool
27
+ */
28
+ public function isValidTheme( WP_Theme $theme ) {
29
+ return ( $this->checkCapability() && $theme->exists() && ! $theme->parent() );
30
+ }
31
+
32
+ /**
33
+ * @return string
34
+ */
35
+ public function nonce() {
36
+ return wp_create_nonce( $this->nonceName() );
37
+ }
38
+
39
+ /**
40
+ * @return string
41
+ */
42
+ public function nonceName() {
43
+ return "child_themify";
44
+ }
45
+
46
+ public function showInterface() {
47
+ $theme = empty( $_GET['theme'] ) ? '' : $_GET['theme'];
48
+ $theme = wp_get_theme( $theme );
49
+ if ( $this->checkCreds( $theme ) ) {
50
+ return;
51
+ }
52
+ $this->display( $theme );
53
+ }
54
+
55
+ /**
56
+ * @param WP_Theme $theme
57
+ */
58
+ public function display( WP_Theme $theme ) {
59
+ settings_errors();
60
+ ?>
61
+ <div class="wrap">
62
+ <h2><?php echo esc_html( sprintf( _x( 'Create a child theme from %s', 'The placeholder is for a theme\'s name', 'child-themify' ), $theme->name ) ); ?></h2>
63
+
64
+ <form method="post" action="<?php echo esc_url( $this->getLink( $theme ) ); ?>">
65
+ <label><?php esc_html_e( 'Name your child theme', 'child-themify' ); ?></label><br>
66
+ <input type="text" name="new_theme" />
67
+ <?php submit_button( __( "Let's go!", 'child-themify' ) ); ?>
68
+ </form>
69
+ </div>
70
+ <?php
71
+ // End of Display
72
+ }
73
+
74
+ /**
75
+ * @param WP_Theme $theme
76
+ *
77
+ * @return bool
78
+ */
79
+ public function checkCreds( WP_Theme $theme ) {
80
+ if ( empty( $_POST ) ) {
81
+ return false;
82
+ }
83
+ $this->isActionAllowed( $theme );
84
+
85
+ $url = $this->getLink( $theme );
86
+ if ( ( $creds = request_filesystem_credentials( $url, '', false, get_theme_root(), array( 'new_theme' ) ) ) === false ) {
87
+ return true;
88
+ }
89
+ if ( ! WP_Filesystem( $creds, get_theme_root() ) ) {
90
+ request_filesystem_credentials( $url, '', true, get_theme_root(), array( 'new_theme' ) );
91
+ return true;
92
+ }
93
+ $this->create( $_POST['new_theme'], $theme );
94
+ }
95
+
96
+ /**
97
+ * Get the link to create a child theme from a theme
98
+ *
99
+ * @param WP_Theme $theme The template theme's directory
100
+ *
101
+ * @return string The url to create a child theme
102
+ */
103
+ public function getLink( WP_Theme $theme ) {
104
+ // If the current user can't install a theme, the theme doesn't exist
105
+ if ( ! $this->isValidTheme( $theme ) ) {
106
+ return '';
107
+ }
108
+
109
+ $args = array(
110
+ 'action' => 'child-themify',
111
+ 'theme' => $theme->get_stylesheet(),
112
+ '_ctf_nonce' => $this->nonce( $theme ),
113
+ );
114
+ return add_query_arg( $args, $this->getBaseLink() );
115
+ }
116
+
117
+ /**
118
+ * Get the base link for the correct themes.php page
119
+ *
120
+ * If the site is a multisite network, it will use the network admin.
121
+ * Otherwise it'll just use the normal admin.
122
+ *
123
+ * @return string
124
+ */
125
+ public function getBaseLink() {
126
+ return is_multisite() ? network_admin_url( 'themes.php' ) : admin_url( 'themes.php' );
127
+ }
128
+
129
+ /**
130
+ * Add the link for creating a child theme to the theme action links
131
+ *
132
+ * @param array $links
133
+ * @param string|WP_Theme $theme
134
+ *
135
+ * @return array An array of action links
136
+ */
137
+ public function addActionLink( array $links, $theme ) {
138
+ if ( ! ( $theme instanceof WP_Theme ) ) {
139
+ $theme = wp_get_theme( $theme );
140
+ }
141
+ if ( ! $this->isValidTheme( $theme ) ) {
142
+ return $links;
143
+ }
144
+ $link = $this->getLink( $theme );
145
+ $html = sprintf( "<a href=\"$link\">%s</a>", __( 'Create a child theme', 'child-themify' ) );
146
+
147
+ $links['child-themify'] = $html;
148
+ return $links;
149
+ }
150
+
151
+ /**
152
+ * Runs the actual child theme creation functionality
153
+ *
154
+ * @global WP_Filesystem_Base $wp_filesystem
155
+ *
156
+ * @param string $new_theme
157
+ * @param WP_Theme $template
158
+ *
159
+ * @throws Exception If the global filesystem object isn't available
160
+ */
161
+ public function create( $new_theme, WP_Theme $template ) {
162
+ global $wp_filesystem;
163
+ if ( ! ( $wp_filesystem instanceof WP_Filesystem_Base ) ) {
164
+ if ( ! WP_Filesystem() ) {
165
+ throw new Exception( __( 'Could not access the filesystem!', 'child-themify' ) );
166
+ }
167
+ }
168
+ $oldStylesheet = $template->get_stylesheet();
169
+ $oldName = $template->name;
170
+ $new_theme_directory = trailingslashit( get_theme_root() ) . sanitize_file_name( strtolower( $new_theme ) );
171
+ $wp_filesystem->mkdir( $new_theme_directory );
172
+ $newStylesheet = trailingslashit( $new_theme_directory ) . 'style.css';
173
+ $wp_filesystem->touch( $newStylesheet );
174
+ $stylesheetContents = <<<EOF
175
+ /*
176
+ Theme Name: $new_theme
177
+ Version: 1.0
178
+ Description: A child theme of $oldName
179
+ Template: $oldStylesheet
180
+ */
181
+
182
+ @import url("../$oldStylesheet/style.css");
183
+
184
+ EOF;
185
+ $wp_filesystem->put_contents( $newStylesheet, $stylesheetContents );
186
+ add_settings_error( '', 'child-themify', __( 'Your child theme was created successfully.', 'child-themify' ), 'updated' );
187
+ }
188
+
189
+ public function loadThemesPage() {
190
+ if ( ! $this->isChildThemifyPage() ) {
191
+ if ( ! is_multisite() ) {
192
+ add_action( 'admin_footer', array( $this, 'linkThemes' ) );
193
+ }
194
+ return;
195
+ }
196
+ $this->loadFile( ABSPATH . 'wp-admin/admin-header.php' );
197
+ $this->showInterface();
198
+ $this->loadFile( ABSPATH . 'wp-admin/admin-footer.php' );
199
+ exit;
200
+ }
201
+
202
+ public function loadFile( $file ) {
203
+ require $file;
204
+ }
205
+
206
+ public function isChildThemifyPage() {
207
+ return ( ! empty( $_GET['action'] ) && $_GET['action'] === 'child-themify' );
208
+ }
209
+
210
+ public function linkThemes() {
211
+ if ( ! $this->checkCapability() ) {
212
+ return;
213
+ }
214
+ $js = defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ? 'js' : 'min.js';
215
+ $filename = "assets/js/child-themify.$js";
216
+ wp_enqueue_script( 'child-themify', plugins_url( $filename, CTF_PATH ), array( 'theme' ), CTF_VERSION, true );
217
+ wp_localize_script( 'child-themify', 'childThemify', array(
218
+ 'createAChildTheme' => __( 'Create a child theme', 'child-themify' ),
219
+ 'nonce' => $this->nonce(),
220
+ ) );
221
+ }
222
+
223
+ public function init() {
224
+ load_plugin_textdomain( 'child-themify', false, basename( dirname( __FILE__ ) ) . '/languages' );
225
+ add_filter( 'theme_action_links', array( $this, 'addActionLink' ), 10, 2 );
226
+ add_action( 'load-themes.php', array( $this, 'loadThemesPage' ) );
227
+ }
228
+
229
+ }
230
+
readme.txt CHANGED
@@ -2,8 +2,8 @@
2
  Contributors: JohnPBloch
3
  Tags: themes, child, theme
4
  Requires at least: 3.4.2
5
- Tested up to: 3.5
6
- Stable tag: 1.0.1
7
  License: GPLv2 or later
8
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
9
 
@@ -32,6 +32,9 @@ None yet.
32
 
33
  == Changelog ==
34
 
 
 
 
35
  = 1.0.1 =
36
  * Add a semicolon to the end of the @import line in the stylesheet. Props to Luis Alejandre (wpthemedetector.com) for finding and solving.
37
 
@@ -40,5 +43,8 @@ None yet.
40
 
41
  == Upgrade Notice ==
42
 
 
 
 
43
  = 1.0.1 =
44
  This version fixes a bug that will prevent some users' css from taking effect in new child themes.
2
  Contributors: JohnPBloch
3
  Tags: themes, child, theme
4
  Requires at least: 3.4.2
5
+ Tested up to: 3.8
6
+ Stable tag: 1.0.2
7
  License: GPLv2 or later
8
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
9
 
32
 
33
  == Changelog ==
34
 
35
+ = 1.0.2 =
36
+ * Added support for WP 3.8
37
+
38
  = 1.0.1 =
39
  * Add a semicolon to the end of the @import line in the stylesheet. Props to Luis Alejandre (wpthemedetector.com) for finding and solving.
40
 
43
 
44
  == Upgrade Notice ==
45
 
46
+ = 1.0.2 =
47
+ This version fixes the plugin in WordPress 3.8
48
+
49
  = 1.0.1 =
50
  This version fixes a bug that will prevent some users' css from taking effect in new child themes.