Version Description
- New Feature: Better child theme handling for multisite. Moved interface to Themes menu and check for network enabled.
- Fix: Restrict child theme configurator access to install_themes capability
- Fix: Preview links to Themes admin if not network enabled to prevent 'Cheatin, uh?' error.
Download this release
Release Info
Developer | lilaeamedia |
Plugin | Child Theme Configurator |
Version | 1.6.3 |
Comparing to | |
See all releases |
Code changes from version 1.6.2.1 to 1.6.3
- child-theme-configurator.php +42 -24
- includes/class-ctc-css.php +416 -403
- includes/class-ctc-ui.php +82 -74
- includes/class-ctc.php +404 -393
- includes/forms/at-import.php +6 -6
- includes/forms/backup.php +3 -3
- includes/forms/file.php +2 -2
- includes/forms/fileform.php +17 -16
- includes/forms/files.php +17 -17
- includes/forms/image.php +1 -1
- includes/forms/images.php +4 -4
- includes/forms/main.php +9 -9
- includes/forms/parent-child.php +49 -49
- includes/forms/query-selector.php +13 -13
- includes/forms/related.php +1 -1
- includes/forms/rule-value.php +5 -5
- includes/forms/tabs.php +11 -11
- includes/forms/themepreview.php +11 -7
- includes/help/help_en_US.php +2 -14
- js/chld-thm-cfg.js +3 -2
- readme.txt +34 -35
child-theme-configurator.php
CHANGED
@@ -1,23 +1,23 @@
|
|
1 |
<?php
|
2 |
// Exit if accessed directly
|
3 |
-
if ( !defined('ABSPATH')) exit;
|
4 |
|
5 |
/*
|
6 |
Plugin Name: Child Theme Configurator
|
7 |
Plugin URI: http://www.lilaeamedia.com/plugins/child-theme-configurator/
|
8 |
-
Description: Create a Child Theme
|
9 |
-
Version: 1.6.
|
10 |
Author: Lilaea Media
|
11 |
Author URI: http://www.lilaeamedia.com/
|
12 |
Text Domain: chld_thm_cfg
|
13 |
Domain Path: /lang
|
14 |
License: GPLv2
|
15 |
-
Copyright (C) 2014 Lilaea Media
|
16 |
*/
|
17 |
|
18 |
-
defined( 'LF' ) or define( 'LF', "\n");
|
19 |
defined( 'CHLD_THM_CFG_OPTIONS' ) or define( 'CHLD_THM_CFG_OPTIONS', 'chld_thm_cfg_options' );
|
20 |
-
defined( 'CHLD_THM_CFG_VERSION' ) or define( 'CHLD_THM_CFG_VERSION', '1.6.
|
21 |
defined( 'CHLD_THM_CFG_MIN_WP_VERSION' ) or define( 'CHLD_THM_CFG_MIN_WP_VERSION', '3.7' );
|
22 |
defined( 'CHLD_THM_CFG_MAX_SELECTORS' ) or define( 'CHLD_THM_CFG_MAX_SELECTORS', '50000' );
|
23 |
defined( 'CHLD_THM_CFG_MAX_RECURSE_LOOPS' ) or define( 'CHLD_THM_CFG_MAX_RECURSE_LOOPS', '1000' );
|
@@ -25,23 +25,26 @@ if ( !defined('ABSPATH')) exit;
|
|
25 |
|
26 |
class ChildThemeConfigurator {
|
27 |
static function init() {
|
28 |
-
|
29 |
-
|
|
|
30 |
global $wp_version;
|
31 |
-
if (version_compare($wp_version, CHLD_THM_CFG_MIN_WP_VERSION) < 0):
|
32 |
-
add_action('admin_notices',
|
33 |
return;
|
34 |
endif;
|
35 |
// setup admin hooks
|
36 |
-
add_action( '
|
37 |
-
add_action( '
|
38 |
-
|
|
|
|
|
39 |
}
|
40 |
static function ctc() {
|
41 |
// create admin object
|
42 |
global $chld_thm_cfg;
|
43 |
if ( !isset( $chld_thm_cfg ) ):
|
44 |
-
include_once( dirname(__FILE__) . '/includes/class-ctc.php' );
|
45 |
$chld_thm_cfg = new ChildThemeConfiguratorAdmin( __FILE__ );
|
46 |
endif;
|
47 |
return $chld_thm_cfg;
|
@@ -54,16 +57,31 @@ if ( !defined('ABSPATH')) exit;
|
|
54 |
// ajax read
|
55 |
self::ctc()->ajax_query_css();
|
56 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
57 |
static function admin() {
|
58 |
-
// setup admin page
|
59 |
$hook = add_management_page(
|
60 |
-
|
61 |
-
|
62 |
-
|
63 |
-
|
64 |
-
|
65 |
);
|
66 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
67 |
}
|
68 |
static function page_init() {
|
69 |
// start admin controller
|
@@ -75,14 +93,14 @@ if ( !defined('ABSPATH')) exit;
|
|
75 |
}
|
76 |
static function version_notice() {
|
77 |
deactivate_plugins( plugin_basename( __FILE__ ) );
|
78 |
-
unset($_GET['activate']);
|
79 |
-
echo '<div class="update-nag"><p>' . sprintf(__('Child Theme Configurator requires WordPress version %s or later.', 'chld_thm_cfg'), CHLD_THM_CFG_MIN_WP_VERSION) . '</p></div>' . LF;
|
80 |
}
|
81 |
}
|
82 |
|
83 |
if ( is_admin() ) ChildThemeConfigurator::init();
|
84 |
|
85 |
-
register_uninstall_hook( __FILE__
|
86 |
|
87 |
function chld_thm_cfg_delete_plugin() {
|
88 |
delete_option( CHLD_THM_CFG_OPTIONS );
|
1 |
<?php
|
2 |
// Exit if accessed directly
|
3 |
+
if ( !defined( 'ABSPATH' ) ) exit;
|
4 |
|
5 |
/*
|
6 |
Plugin Name: Child Theme Configurator
|
7 |
Plugin URI: http://www.lilaeamedia.com/plugins/child-theme-configurator/
|
8 |
+
Description: Create a Child Theme and customize the stylesheet as you wish. Search, preview and modify any selector, rule or value using this fast CSS editor.
|
9 |
+
Version: 1.6.3
|
10 |
Author: Lilaea Media
|
11 |
Author URI: http://www.lilaeamedia.com/
|
12 |
Text Domain: chld_thm_cfg
|
13 |
Domain Path: /lang
|
14 |
License: GPLv2
|
15 |
+
Copyright (C) 2014-2015 Lilaea Media
|
16 |
*/
|
17 |
|
18 |
+
defined( 'LF' ) or define( 'LF', "\n" );
|
19 |
defined( 'CHLD_THM_CFG_OPTIONS' ) or define( 'CHLD_THM_CFG_OPTIONS', 'chld_thm_cfg_options' );
|
20 |
+
defined( 'CHLD_THM_CFG_VERSION' ) or define( 'CHLD_THM_CFG_VERSION', '1.6.3' );
|
21 |
defined( 'CHLD_THM_CFG_MIN_WP_VERSION' ) or define( 'CHLD_THM_CFG_MIN_WP_VERSION', '3.7' );
|
22 |
defined( 'CHLD_THM_CFG_MAX_SELECTORS' ) or define( 'CHLD_THM_CFG_MAX_SELECTORS', '50000' );
|
23 |
defined( 'CHLD_THM_CFG_MAX_RECURSE_LOOPS' ) or define( 'CHLD_THM_CFG_MAX_RECURSE_LOOPS', '1000' );
|
25 |
|
26 |
class ChildThemeConfigurator {
|
27 |
static function init() {
|
28 |
+
// initialize languages
|
29 |
+
load_plugin_textdomain( 'chld_thm_cfg', FALSE, basename( dirname( __FILE__ ) ) . '/lang' );
|
30 |
+
// verify WP version support
|
31 |
global $wp_version;
|
32 |
+
if ( version_compare( $wp_version, CHLD_THM_CFG_MIN_WP_VERSION ) < 0 ):
|
33 |
+
add_action( 'admin_notices', 'ChildthemeConfigurator::version_notice' );
|
34 |
return;
|
35 |
endif;
|
36 |
// setup admin hooks
|
37 |
+
add_action( 'network_admin_menu', 'ChildThemeConfigurator::network_admin' );
|
38 |
+
add_action( 'admin_menu', 'ChildThemeConfigurator::admin' );
|
39 |
+
// setup ajax actions
|
40 |
+
add_action( 'wp_ajax_ctc_update', 'ChildThemeConfigurator::save' );
|
41 |
+
add_action( 'wp_ajax_ctc_query', 'ChildThemeConfigurator::query' );
|
42 |
}
|
43 |
static function ctc() {
|
44 |
// create admin object
|
45 |
global $chld_thm_cfg;
|
46 |
if ( !isset( $chld_thm_cfg ) ):
|
47 |
+
include_once( dirname( __FILE__ ) . '/includes/class-ctc.php' );
|
48 |
$chld_thm_cfg = new ChildThemeConfiguratorAdmin( __FILE__ );
|
49 |
endif;
|
50 |
return $chld_thm_cfg;
|
57 |
// ajax read
|
58 |
self::ctc()->ajax_query_css();
|
59 |
}
|
60 |
+
static function network_admin() {
|
61 |
+
$hook = add_theme_page(
|
62 |
+
__( 'Child Theme Configurator', 'chld_thm_cfg' ),
|
63 |
+
__( 'Child Themes', 'chld_thm_cfg' ),
|
64 |
+
'install_themes',
|
65 |
+
CHLD_THM_CFG_MENU,
|
66 |
+
'ChildThemeConfigurator::render'
|
67 |
+
);
|
68 |
+
add_action( 'load-' . $hook, 'ChildThemeConfigurator::page_init' );
|
69 |
+
}
|
70 |
static function admin() {
|
|
|
71 |
$hook = add_management_page(
|
72 |
+
__( 'Child Theme Configurator', 'chld_thm_cfg' ),
|
73 |
+
__( 'Child Themes', 'chld_thm_cfg' ),
|
74 |
+
'install_themes',
|
75 |
+
CHLD_THM_CFG_MENU,
|
76 |
+
'ChildThemeConfigurator::render'
|
77 |
);
|
78 |
+
add_filter( 'plugin_action_links_' . plugin_basename( __FILE__ ), 'ChildThemeConfigurator::action_links' );
|
79 |
+
add_action( 'load-' . $hook, 'ChildThemeConfigurator::page_init' );
|
80 |
+
}
|
81 |
+
static function action_links( $actions ) {
|
82 |
+
$actions[] = '<a href="' . admin_url( 'tools.php?page=' . CHLD_THM_CFG_MENU ). '">'
|
83 |
+
. __( 'Child Themes', 'chld_thm_cfg' ) . '</a>' . LF;
|
84 |
+
return $actions;
|
85 |
}
|
86 |
static function page_init() {
|
87 |
// start admin controller
|
93 |
}
|
94 |
static function version_notice() {
|
95 |
deactivate_plugins( plugin_basename( __FILE__ ) );
|
96 |
+
unset( $_GET['activate'] );
|
97 |
+
echo '<div class="update-nag"><p>' . sprintf( __( 'Child Theme Configurator requires WordPress version %s or later.', 'chld_thm_cfg' ), CHLD_THM_CFG_MIN_WP_VERSION ) . '</p></div>' . LF;
|
98 |
}
|
99 |
}
|
100 |
|
101 |
if ( is_admin() ) ChildThemeConfigurator::init();
|
102 |
|
103 |
+
register_uninstall_hook( __FILE__, 'chld_thm_cfg_delete_plugin' );
|
104 |
|
105 |
function chld_thm_cfg_delete_plugin() {
|
106 |
delete_option( CHLD_THM_CFG_OPTIONS );
|
includes/class-ctc-css.php
CHANGED
@@ -1,18 +1,18 @@
|
|
1 |
<?php
|
2 |
// Exit if accessed directly
|
3 |
-
if ( !defined('ABSPATH')) exit;
|
4 |
|
5 |
/*
|
6 |
Class: ChildThemeConfiguratorCSS
|
7 |
Plugin URI: http://www.lilaeamedia.com/plugins/child-theme-configurator/
|
8 |
Description: Handles all CSS output, parsing, normalization
|
9 |
-
Version: 1.6.
|
10 |
Author: Lilaea Media
|
11 |
Author URI: http://www.lilaeamedia.com/
|
12 |
Text Domain: chld_thm_cfg
|
13 |
Domain Path: /lang
|
14 |
License: GPLv2
|
15 |
-
Copyright (C) 2014 Lilaea Media
|
16 |
*/
|
17 |
class ChildThemeConfiguratorCSS {
|
18 |
// data dictionaries
|
@@ -104,68 +104,68 @@ class ChildThemeConfiguratorCSS {
|
|
104 |
$this->sel_ndx = array();
|
105 |
$this->val_ndx = array();
|
106 |
$this->parntss = array();
|
107 |
-
$this->imports = array('child' => array(), 'parnt' => array());
|
108 |
}
|
109 |
-
|
110 |
function ctc() {
|
111 |
global $chld_thm_cfg;
|
112 |
return $chld_thm_cfg;
|
113 |
}
|
114 |
-
|
115 |
function read_config() {
|
116 |
|
117 |
-
if ($configarray = get_option(CHLD_THM_CFG_OPTIONS . '_configvars')):
|
118 |
-
foreach ($this->configvars as $configkey)
|
119 |
-
if (isset($configarray[$configkey]))
|
120 |
$this->{$configkey} = $configarray[$configkey];
|
121 |
-
foreach ($this->dicts as $configkey):
|
122 |
-
if ($configarray = get_option(CHLD_THM_CFG_OPTIONS . '_' . $configkey))
|
123 |
$this->{$configkey} = $configarray;
|
124 |
endforeach;
|
125 |
else:
|
126 |
return FALSE;
|
127 |
endif;
|
128 |
}
|
129 |
-
|
130 |
function save_config() {
|
131 |
|
132 |
$configarray = array();
|
133 |
-
foreach ($this->configvars as $configkey)
|
134 |
$configarray[$configkey] = $this->{$configkey};
|
135 |
-
update_option(CHLD_THM_CFG_OPTIONS . '_configvars', $configarray);
|
136 |
-
foreach ($this->dicts as $configkey)
|
137 |
-
update_option(CHLD_THM_CFG_OPTIONS . '_' . $configkey, $this->{$configkey});
|
138 |
// remove pre 1.5.4 options
|
139 |
-
delete_option(CHLD_THM_CFG_OPTIONS);
|
140 |
}
|
141 |
/*
|
142 |
* get_prop
|
143 |
-
* Getter interface (data sliced different ways depending on objname)
|
144 |
*/
|
145 |
-
function get_prop($objname, $params =
|
146 |
-
switch ($objname):
|
147 |
case 'imports':
|
148 |
-
return $this->obj_to_utf8(is_array($this->imports['child']) ? (current($this->imports['child']) == 1 ? array_keys($this->imports['child']) : array_keys(array_flip($this->imports['child']))) : array());
|
149 |
case 'sel_ndx':
|
150 |
-
return $this->obj_to_utf8($this->denorm_sel_ndx(empty($params['key'])?
|
151 |
case 'rule_val':
|
152 |
-
return empty($params['key']) ? array() : $this->denorm_rule_val($params['key']);
|
153 |
case 'val_qry':
|
154 |
-
if (isset($params['rule']) && isset($this->dict_rule[$params['rule']])):
|
155 |
-
return empty($params['key']) ?
|
156 |
-
array() : $this->denorm_val_query($params['key'], $params['rule']);
|
157 |
endif;
|
158 |
case 'sel_val':
|
159 |
-
return empty($params['key']) ?
|
160 |
-
array() : $this->denorm_sel_val($params['key']);
|
161 |
case 'rule':
|
162 |
-
return $this->obj_to_utf8(array_flip($this->dict_rule));
|
163 |
case 'child':
|
164 |
return $this->child;
|
165 |
case 'parnt':
|
166 |
return $this->parnt;
|
167 |
case 'parntss':
|
168 |
-
return isset($this->parntss) ? $this->parntss : array();
|
169 |
case 'configtype':
|
170 |
return $this->configtype;
|
171 |
case 'child_name':
|
@@ -176,18 +176,18 @@ class ChildThemeConfiguratorCSS {
|
|
176 |
return $this->child_version;
|
177 |
case 'preview':
|
178 |
$this->styles = '';
|
179 |
-
if (empty($params['key']) || 'child' == $params['key']):
|
180 |
-
$this->read_stylesheet('child');
|
181 |
else:
|
182 |
-
if (isset($this->parntss)):
|
183 |
-
foreach ($this->parntss as $template):
|
184 |
$this->styles .= '/*** BEGIN ' . $template . ' ***/' . LF;
|
185 |
-
$this->read_stylesheet('parnt', $template);
|
186 |
$this->styles .= '/*** END ' . $template . ' ***/' . LF;
|
187 |
endforeach;
|
188 |
endif;
|
189 |
$this->styles .= '/*** BEGIN style.css ***/' . LF;
|
190 |
-
$this->read_stylesheet('parnt');
|
191 |
$this->styles .= '/*** END style.css ***/' . LF;
|
192 |
endif;
|
193 |
$this->normalize_css();
|
@@ -200,55 +200,56 @@ class ChildThemeConfiguratorCSS {
|
|
200 |
* set_prop
|
201 |
* Setter interface (scalar values only)
|
202 |
*/
|
203 |
-
function set_prop($prop, $value) {
|
204 |
-
if (is_scalar($this->{$prop}))
|
205 |
$this->{$prop} = $value;
|
206 |
else return FALSE;
|
207 |
}
|
208 |
-
|
209 |
function normalize_css() {
|
210 |
-
if (preg_match("/(\}[\w\#\.]|; *\})/", $this->styles)): // prettify compressed CSS
|
211 |
-
$this->styles = preg_replace("/\*\/\s*/s", "*/\n", $this->styles); // end comment
|
212 |
-
$this->styles = preg_replace("/\{\s*/s", " {\n ", $this->styles); // open brace
|
213 |
-
$this->styles = preg_replace("/;\s*/s", ";\n ", $this->styles); // semicolon
|
214 |
-
$this->styles = preg_replace("/\s*\}\s*/s", "\n}\n", $this->styles); // close brace
|
215 |
endif;
|
216 |
}
|
217 |
-
|
218 |
function get_css_header() {
|
219 |
-
$parnt = $this->get_prop('parnt');
|
220 |
return '/*' . LF
|
221 |
-
. 'Theme Name: ' . $this->get_prop('child_name') . LF
|
222 |
. 'Template: ' . $parnt . LF
|
223 |
-
. 'Author: ' . $this->get_prop('author'). LF
|
224 |
-
. 'Version: ' . $this->get_prop('version') . LF
|
225 |
-
. 'Updated: ' . current_time('mysql') . LF
|
226 |
. '*/' . LF . LF
|
227 |
. '@charset "UTF-8";' . LF . LF
|
228 |
-
. ('import' == $this->enqueue ? '@import url(\'../' . $parnt . '/style.css\');' . LF : '');
|
229 |
}
|
230 |
-
|
231 |
-
function get_child_target($file = 'style.css') {
|
232 |
-
return trailingslashit(get_theme_root()) . trailingslashit($this->get_prop('child')) . $file;
|
233 |
}
|
234 |
-
|
235 |
-
|
|
|
236 |
}
|
237 |
|
238 |
/*
|
239 |
* update_arrays
|
240 |
* accepts CSS properties as raw strings and normilizes into
|
241 |
* CTC object arrays, creating update cache in the process.
|
242 |
-
* Update cache is returned to UI via AJAX to refresh page
|
243 |
*/
|
244 |
-
function update_arrays($template, $query, $sel, $rule =
|
245 |
|
246 |
// normalize selector styling
|
247 |
-
$sel = implode(', ', preg_split('#\s*,\s*#s', trim($sel)));
|
248 |
// add selector and query to index
|
249 |
-
if (!isset($this->dict_query[$query])) $this->dict_query[$query] = ++$this->querykey;
|
250 |
-
if (!isset($this->dict_sel[$sel])) $this->dict_sel[$sel] = ++$this->selkey;
|
251 |
-
if (!isset($this->sel_ndx[$this->dict_query[$query]][$this->dict_sel[$sel]])):
|
252 |
// increment key number
|
253 |
$this->sel_ndx[$this->dict_query[$query]][$this->dict_sel[$sel]] = ++$this->qskey;
|
254 |
|
@@ -256,7 +257,7 @@ class ChildThemeConfiguratorCSS {
|
|
256 |
$this->dict_qs[$this->qskey]['q'] = $this->dict_query[$query];
|
257 |
// tell the UI to update a single cached query/selector lookup by passing 'qsid' as the key
|
258 |
// (normally the entire array is replaced):
|
259 |
-
if ($this->ctc()->cache_updates)
|
260 |
$this->ctc()->updates[] = array(
|
261 |
'obj' => 'sel_ndx',
|
262 |
'key' => 'qsid',
|
@@ -268,14 +269,14 @@ class ChildThemeConfiguratorCSS {
|
|
268 |
);
|
269 |
endif;
|
270 |
// update sequence for this selector if this is a later instance to keep cascade priority
|
271 |
-
if (!isset($this->dict_seq[$this->qskey]))
|
272 |
$this->dict_seq[$this->qskey] = $this->qskey;
|
273 |
// set data and value
|
274 |
-
if ($rule):
|
275 |
-
if (!isset($this->dict_rule[$rule])):
|
276 |
$this->dict_rule[$rule] = ++$this->rulekey;
|
277 |
// tell the UI to update a single cached rule:
|
278 |
-
if ($this->ctc()->cache_updates):
|
279 |
$this->ctc()->updates[] = array(
|
280 |
'obj' => 'rule',
|
281 |
'key' => $this->rulekey,
|
@@ -285,24 +286,24 @@ class ChildThemeConfiguratorCSS {
|
|
285 |
endif;
|
286 |
$qsid = $this->sel_ndx[$this->dict_query[$query]][$this->dict_sel[$sel]];
|
287 |
$ruleid = $this->dict_rule[$rule];
|
288 |
-
if (!isset($this->dict_val[$value])):
|
289 |
$this->dict_val[$value] = ++$this->valkey;
|
290 |
endif;
|
291 |
$this->val_ndx[$qsid][$ruleid][$template] = $this->dict_val[$value];
|
292 |
// set the important flag for this value
|
293 |
$this->val_ndx[$qsid][$ruleid]['i_' . $template] = $important;
|
294 |
// tell the UI to add a single cached query/selector data array:
|
295 |
-
if ($this->ctc()->cache_updates):
|
296 |
$updatearr = array(
|
297 |
'obj' => 'sel_val',
|
298 |
'key' => $qsid,
|
299 |
-
'data' => $this->denorm_sel_val($qsid),
|
300 |
);
|
301 |
$this->ctc()->updates[] = $updatearr;
|
302 |
endif;
|
303 |
-
if (isset($seq)): // this is a renamed selector
|
304 |
$this->dict_seq[$qsid] = $seq;
|
305 |
-
if ($this->ctc()->cache_updates):
|
306 |
$this->ctc()->updates[] = array(
|
307 |
'obj' => 'rewrite',
|
308 |
'key' => $qsid,
|
@@ -312,72 +313,75 @@ class ChildThemeConfiguratorCSS {
|
|
312 |
endif;
|
313 |
endif;
|
314 |
}
|
315 |
-
|
316 |
-
function read_stylesheet($template = 'child', $file = 'style.css') {
|
317 |
|
318 |
// these conditions support revert/restore option in 1.6.0+
|
319 |
-
if ('all' == $file) return;
|
320 |
-
elseif ('' == $file) $file = 'style.css';
|
321 |
// end revert/restore conditions
|
322 |
|
323 |
-
$source = $this->get_prop($template);
|
324 |
-
$configtype = $this->get_prop('configtype');
|
325 |
-
if (empty($source) || !is_scalar($source)) return FALSE;
|
326 |
$themedir = get_theme_root() . '/' . $source;
|
327 |
-
$stylesheet = apply_filters('chld_thm_cfg_' . $template, $themedir . '/' . $file , $this);
|
328 |
|
329 |
// read stylesheet
|
330 |
-
if ($stylesheet_verified = $this->is_file_ok($stylesheet, 'read')):
|
331 |
-
$import_url = preg_replace('%^' . preg_quote($themedir) . '/%', '', $stylesheet_verified);
|
332 |
-
$this->styles .= @file_get_contents($stylesheet_verified) . "\n";
|
333 |
endif;
|
334 |
}
|
335 |
-
|
|
|
|
|
|
|
336 |
function recurse_directory( $rootdir, $ext = 'css', $all = FALSE ) {
|
337 |
if ( !$this->is_file_ok( $rootdir, 'search' ) ) return array(); // make sure we are only recursing theme and plugin files
|
338 |
$files = array();
|
339 |
-
$dirs = array($rootdir);
|
340 |
$loops = 0;
|
341 |
if ( 'img' == $ext ):
|
342 |
|
343 |
-
$ext = '(' . implode('|', array_keys($this->ctc()->imgmimes)) . ')';
|
344 |
endif;
|
345 |
-
while(count($dirs) && $loops < CHLD_THM_CFG_MAX_RECURSE_LOOPS ):
|
346 |
$loops++;
|
347 |
-
$dir = array_shift($dirs);
|
348 |
-
if ($handle = opendir($dir)):
|
349 |
-
while (FALSE !== ($file = readdir($handle))):
|
350 |
-
if (preg_match("/^\./", $file)) continue;
|
351 |
-
$filepath = trailingslashit($dir) . $file;
|
352 |
-
if (is_dir($filepath)):
|
353 |
-
array_unshift($dirs, $filepath);
|
354 |
-
if ($all):
|
355 |
$files[] = $filepath;
|
356 |
endif;
|
357 |
-
elseif (is_file($filepath) && ($all || preg_match("/\.".$ext."$/i", $filepath))):
|
358 |
$files[] = $filepath;
|
359 |
endif;
|
360 |
endwhile;
|
361 |
-
closedir($handle);
|
362 |
endif;
|
363 |
endwhile;
|
364 |
return $files;
|
365 |
}
|
366 |
-
|
367 |
-
function convert_parent_rel_url_to_abs_url($url) {
|
368 |
-
$source = $this->get_prop('parnt');
|
369 |
$spliton = '%[/\\\\]%';
|
370 |
-
$dirname = dirname($url);
|
371 |
-
$dirs = preg_split($spliton, $dirname);
|
372 |
$dds = '';
|
373 |
$themeuri = get_theme_root_uri();
|
374 |
-
while (count($dirs)):
|
375 |
-
$thisdir = array_pop($dirs);
|
376 |
-
$upone = implode('/', $dirs);
|
377 |
$dds .= '\.\.\/';
|
378 |
$regex = '%url\([\'" ]*' . $dds . '(.+?)[\'" ]*\)%';
|
379 |
-
$fullurl = $themeuri . '/' . $source . '/' . $upone . ('' == $upone ? '' : '/' );
|
380 |
-
$this->styles = preg_replace($regex, "url(" . $fullurl . "$1)", $this->styles);
|
381 |
endwhile;
|
382 |
}
|
383 |
/*
|
@@ -386,94 +390,94 @@ class ChildThemeConfiguratorCSS {
|
|
386 |
*/
|
387 |
function parse_post_data() {
|
388 |
$this->cache_updates = TRUE;
|
389 |
-
if (isset($_POST['ctc_new_selectors'])):
|
390 |
-
$this->styles = $this->parse_css_input(LF . $_POST['ctc_new_selectors']);
|
391 |
-
$this->parse_css('child',
|
392 |
-
(isset($_POST['ctc_sel_ovrd_query'])?trim($_POST['ctc_sel_ovrd_query']):
|
393 |
-
elseif (isset($_POST['ctc_child_imports'])):
|
394 |
$this->imports['child'] = array();
|
395 |
-
$this->styles = $this->parse_css_input($_POST['ctc_child_imports']);
|
396 |
-
$this->parse_css('child');
|
397 |
else:
|
398 |
-
$newselector = isset($_POST['ctc_rewrite_selector']) ? $this->sanitize($this->parse_css_input($_POST['ctc_rewrite_selector'])) : NULL;
|
399 |
// set the custom sequence value
|
400 |
-
foreach (preg_grep('#^ctc_ovrd_child_seq_#', array_keys($_POST)) as $post_key):
|
401 |
-
if (preg_match('#^ctc_ovrd_child_seq_(\d+)$#', $post_key, $matches)):
|
402 |
$qsid = $matches[1];
|
403 |
-
$this->dict_seq[$qsid] = intval($_POST[$post_key]);
|
404 |
endif;
|
405 |
endforeach;
|
406 |
$parts = array();
|
407 |
-
foreach (preg_grep('#^ctc_(ovrd|\d+)_child#', array_keys($_POST)) as $post_key):
|
408 |
-
if (preg_match('#^ctc_(ovrd|\d+)_child_([\w\-]+?)_(\d+?)(_(.+))?$#', $post_key, $matches)):
|
409 |
$valid = $matches[1];
|
410 |
$rule = $matches[2];
|
411 |
-
if (
|
412 |
$ruleid = $this->dict_rule[$rule];
|
413 |
$qsid = $matches[3];
|
414 |
-
$value = $this->normalize_color($this->sanitize($this->parse_css_input($_POST[$post_key])));
|
415 |
-
$important = $this->is_important($value);
|
416 |
-
if (!empty($_POST['ctc_' . $valid . '_child_' . $rule . '_i_' . $qsid])) $important = 1;
|
417 |
|
418 |
-
$selarr = $this->denorm_query_sel($qsid);
|
419 |
-
if (!empty($matches[5])):
|
420 |
$parts[$qsid][$rule][$matches[5]] = $value;
|
421 |
$parts[$qsid][$rule]['important'] = $important;
|
422 |
$parts[$qsid][$rule]['query'] = $selarr['query'];
|
423 |
$parts[$qsid][$rule]['selector'] = $selarr['selector'];
|
424 |
else:
|
425 |
-
if ($newselector && $newselector != $selarr['selector']):
|
426 |
// If this is a renamed selector, add new selector to array
|
427 |
// and clear original child selector values.
|
428 |
// Passing the sequence in the last argument serves two purposes:
|
429 |
// 1. sets sequence for new renamed selector.
|
430 |
// 2. tells the update_arrays function to flag this as a
|
431 |
// renamed selector to pass back in result array.
|
432 |
-
$this->update_arrays('child', $selarr['query'], $newselector,
|
433 |
-
$rule, trim($value), $important, $this->dict_seq[$qsid]);
|
434 |
-
$this->update_arrays('child', $selarr['query'], $selarr['selector'], $rule, '');
|
435 |
else:
|
436 |
// Otherwise, just update with the new values:
|
437 |
-
$this->update_arrays('child', $selarr['query'], $selarr['selector'],
|
438 |
-
$rule, trim($value), $important);
|
439 |
endif;
|
440 |
endif;
|
441 |
endif;
|
442 |
endforeach;
|
443 |
-
foreach ($parts as $qsid => $rule_arr):
|
444 |
-
foreach ($rule_arr as $rule => $rule_part):
|
445 |
-
if ('background' == $rule):
|
446 |
$value = $rule_part['background_url'];
|
447 |
-
elseif ('background-image' == $rule):
|
448 |
-
if (empty($rule_part['background_url'])):
|
449 |
-
if (empty($rule_part['background_color2'])):
|
450 |
$value = '';
|
451 |
else:
|
452 |
-
$value = implode(':', array(
|
453 |
$rule_part['background_origin'],
|
454 |
$rule_part['background_color1'], '0%',
|
455 |
$rule_part['background_color2'], '100%'
|
456 |
-
));
|
457 |
endif;
|
458 |
else:
|
459 |
$value = $rule_part['background_url'];
|
460 |
endif;
|
461 |
-
elseif (preg_match('#^border(\-(top|right|bottom|left))?$#', $rule)):
|
462 |
-
$value = implode(' ', array(
|
463 |
$rule_part['border_width'],
|
464 |
$rule_part['border_style'],
|
465 |
$rule_part['border_color']
|
466 |
-
));
|
467 |
else:
|
468 |
$value = '';
|
469 |
endif;
|
470 |
-
if ($newselector && $newselector != $rule_part['selector']):
|
471 |
-
$this->update_arrays('child', $rule_part['query'], $newselector,
|
472 |
-
$rule, trim($value), $rule_part['important'], $this->dict_seq[$qsid]);
|
473 |
-
$this->update_arrays('child', $rule_part['query'], $rule_part['selector'], $rule, '');
|
474 |
else:
|
475 |
-
$this->update_arrays('child', $rule_part['query'], $rule_part['selector'],
|
476 |
-
$rule, trim($value), $rule_part['important']);
|
477 |
endif;
|
478 |
endforeach;
|
479 |
endforeach;
|
@@ -485,130 +489,132 @@ class ChildThemeConfiguratorCSS {
|
|
485 |
* Normalize raw user CSS input so that the parser can read it.
|
486 |
* TODO: this is a stub for future use
|
487 |
*/
|
488 |
-
function parse_css_input($styles) {
|
489 |
-
return $this->repl_octal(stripslashes($this->esc_octal($styles)));
|
490 |
}
|
491 |
-
|
492 |
-
function sanitize($styles) {
|
493 |
-
return sanitize_text_field(preg_replace( '/[^[:print:]]/', '', $styles));
|
494 |
}
|
495 |
-
|
496 |
-
function esc_octal($styles){
|
497 |
-
return preg_replace("#(['\"])\\\\([0-9a-f]{4})(['\"])#i", "$1##bs##$2$3", $styles);
|
498 |
}
|
499 |
-
|
500 |
-
|
|
|
501 |
}
|
502 |
/*
|
503 |
* parse_css_file
|
504 |
* reads stylesheet to get WordPress meta data and passes rest to parse_css
|
505 |
*/
|
506 |
-
function parse_css_file($template, $file = 'style.css') {
|
507 |
|
508 |
$this->ctc()->cache_updates = FALSE;
|
509 |
$this->styles = ''; // reset styles
|
510 |
-
$this->read_stylesheet($template, $file);
|
511 |
// get theme name
|
512 |
$regex = '#Theme Name:\s*(.+?)\n#i';
|
513 |
-
preg_match($regex, $this->styles, $matches);
|
514 |
-
$child_name = $this->get_prop('child_name');
|
515 |
-
if (!empty($matches[1]) && 'child' == $template && empty($child_name)) $this->set_prop('child_name', $matches[1]);
|
516 |
-
$this->parse_css($template);
|
517 |
}
|
518 |
|
519 |
/*
|
520 |
* parse_css
|
521 |
-
*
|
522 |
*/
|
523 |
-
function parse_css($template, $basequery =
|
524 |
-
if (FALSE === strpos($basequery, '@')):
|
525 |
$basequery = 'base';
|
526 |
endif;
|
527 |
$ruleset = array();
|
528 |
// ignore commented code
|
529 |
-
$this->styles = preg_replace('#\/\*.*?\*\/#s', '', $this->styles);
|
530 |
// space brace to ensure correct matching
|
531 |
-
$this->styles = preg_replace('#(\{\s*)#', "$1\n", $this->styles);
|
532 |
// get all imports
|
533 |
-
if ($parse_imports):
|
534 |
|
535 |
$regex = '#(\@import.+?);#';
|
536 |
-
preg_match_all($regex, $this->styles, $matches);
|
537 |
-
foreach (preg_grep('#' . $this->get_prop('parnt') . '\/style\.css#', $matches[1], PREG_GREP_INVERT) as $import)
|
538 |
$this->imports[$template][$import] = 1;
|
539 |
-
if ($this->ctc()->cache_updates):
|
540 |
$this->ctc()->updates[] = array(
|
541 |
'obj' => 'imports',
|
542 |
-
'data' => array_keys($this->imports[$template]),
|
543 |
);
|
544 |
endif;
|
545 |
endif;
|
546 |
// break into @ segments
|
547 |
-
foreach (array(
|
548 |
'#(\@media[^\{]+?)\{(\s*?)\}#', // get an placehoder (empty) media queries
|
549 |
'#(\@media[^\{]+?)\{(.*?\})?\s*?\}#s', // get all other media queries
|
550 |
-
) as $regex): // (((?!\@media).) backreference too memory intensive - rolled back in v 1.4.8.1
|
551 |
-
preg_match_all($regex, $this->styles, $matches);
|
552 |
-
foreach ($matches[1] as $segment):
|
553 |
-
$ruleset[trim($segment)] = array_shift($matches[2]) . (isset($ruleset[trim($segment)])?$ruleset[trim($segment)]:'');
|
554 |
endforeach;
|
555 |
// stripping rulesets leaves base styles
|
556 |
-
$this->styles = preg_replace($regex, '', $this->styles);
|
557 |
endforeach;
|
558 |
$ruleset[$basequery] = $this->styles;
|
559 |
-
foreach ($ruleset as $query => $segment):
|
560 |
// make sure there is semicolon before closing brace
|
561 |
-
$segment = preg_replace('#(\})#', ";$1", $segment);
|
|
|
562 |
$regex = '#\s([\[\.\#\:\w][\w\-\s\(\)\[\]\'\^\*\.\#\+:,"=>]+?)\s*\{(.*?)\}#s'; //
|
563 |
-
preg_match_all($regex, $segment, $matches);
|
564 |
-
foreach($matches[1] as $sel):
|
565 |
-
$stuff = array_shift($matches[2]);
|
566 |
-
$this->update_arrays($template, $query, $sel);
|
567 |
// handle base64 data
|
568 |
$stuff = preg_replace( '#data:([^;]+?);([^\)]+?)\)#s', "data:$1%%semi%%$2)", $stuff );
|
569 |
-
foreach (explode(';', $stuff) as $ruleval):
|
570 |
-
if ($this->qskey > CHLD_THM_CFG_MAX_SELECTORS) break;
|
571 |
-
if (FALSE === strpos($ruleval, ':')) continue;
|
572 |
-
list($rule, $value) = explode(':', $ruleval, 2);
|
573 |
-
$rule = trim($rule);
|
574 |
-
$rule = preg_replace_callback("/[^\w\-]/", array($this, 'to_ascii'), $rule);
|
575 |
// handle base64 data
|
576 |
-
$value = trim(str_replace('%%semi%%', ';', $value));
|
577 |
|
578 |
$rules = $values = array();
|
579 |
// save important flag
|
580 |
-
$important = $this->is_important($value);
|
581 |
// normalize color
|
582 |
-
$value = $this->normalize_color($value);
|
583 |
// normalize font
|
584 |
-
if ('font' == $rule):
|
585 |
-
$this->normalize_font($value, $rules, $values);
|
586 |
// normalize background
|
587 |
-
elseif('background' == $rule):
|
588 |
-
$this->normalize_background($value, $rules, $values);
|
589 |
// normalize margin/padding
|
590 |
-
elseif ('margin' == $rule || 'padding' == $rule):
|
591 |
-
$this->normalize_margin_padding($rule, $value, $rules, $values);
|
592 |
else:
|
593 |
$rules[] = $rule;
|
594 |
$values[] = $value;
|
595 |
endif;
|
596 |
-
foreach ($rules as $rule):
|
597 |
-
$value = trim(array_shift($values));
|
598 |
// normalize zero values
|
599 |
-
$value = preg_replace('#\b0(px|r?em)#', '0', $value);
|
600 |
// normalize gradients
|
601 |
-
if (FALSE !== strpos($value, 'gradient')):
|
602 |
-
if (FALSE !== strpos($rule, 'filter')):
|
603 |
$rule = 'background-image';
|
604 |
continue; // treat as background-image, we'll add filter rule later
|
605 |
endif;
|
606 |
-
if (FALSE !== strpos($value, 'webkit-gradient')) continue; // bail on legacy webkit, we'll add it later
|
607 |
-
$value = $this->encode_gradient($value);
|
608 |
endif;
|
609 |
// normalize common vendor prefixes
|
610 |
-
$rule = preg_replace('#(\-(o|ms|moz|webkit)\-)?(' . implode('|', $this->vendorrule) . ')#', "$3", $rule);
|
611 |
-
$this->update_arrays($template, $query, $sel, $rule, $value, $important);
|
612 |
endforeach;
|
613 |
endforeach;
|
614 |
endforeach;
|
@@ -622,73 +628,73 @@ class ChildThemeConfiguratorCSS {
|
|
622 |
* @media query blocks are sorted using internal heuristics (see sort_queries)
|
623 |
* New selectors are appended to the end of each media query block.
|
624 |
*/
|
625 |
-
function write_css($backup = FALSE) {
|
626 |
// write new stylesheet
|
627 |
-
$output = apply_filters('chld_thm_cfg_css_header', $this->get_css_header(), $this);
|
628 |
-
$imports = $this->get_prop('imports');
|
629 |
-
if (!empty($imports)):
|
630 |
-
foreach ($imports as $import):
|
631 |
$output .= $import . ';' . LF;
|
632 |
endforeach;
|
633 |
endif;
|
634 |
$output .= LF;
|
635 |
// turn the dictionaries into indexes (value => id into id => value):
|
636 |
-
$rulearr = array_flip($this->dict_rule);
|
637 |
-
$valarr = array_flip($this->dict_val);
|
638 |
-
$selarr = array_flip($this->dict_sel);
|
639 |
-
foreach ($this->sort_queries() as $query => $sort_order):
|
640 |
$has_selector = 0;
|
641 |
$sel_output = '';
|
642 |
$selectors = $this->sel_ndx[$this->dict_query[$query]];
|
643 |
-
uasort($selectors, array($this, 'cmp_seq'));
|
644 |
-
if ('base' != $query) $sel_output .= $query . ' {' . LF;
|
645 |
-
foreach ($selectors as $selid => $qsid):
|
646 |
$has_value = 0;
|
647 |
$sel = $selarr[$selid];
|
648 |
-
if (!empty($this->val_ndx[$qsid])):
|
649 |
$shorthand = array();
|
650 |
-
foreach ($this->val_ndx[$qsid] as $ruleid => $valid):
|
651 |
-
if (isset($valid['child'])
|
652 |
-
&& isset($valarr[$valid['child']])
|
653 |
&& '' !== $valarr[$valid['child']]
|
654 |
-
&& (!isset($valid['parnt']) || $valid['parnt'] != $valid['child'])):
|
655 |
-
if (! $has_value):
|
656 |
-
$sel_output .= isset($this->dict_seq[$qsid])?'/*' . $this->dict_seq[$qsid] . '*/' . LF:'';
|
657 |
// show load order
|
658 |
$sel_output .= $sel . ' {' . LF;
|
659 |
$has_value = 1;
|
660 |
$has_selector = 1;
|
661 |
endif;
|
662 |
-
$important_parnt = empty($valid['i_parnt']) ? 0 : 1;
|
663 |
-
$important = isset($valid['i_child']) ? $valid['i_child'] : $important_parnt;
|
664 |
-
$sel_output .= $this->add_vendor_rules($rulearr[$ruleid], $valarr[$valid['child']], $shorthand, $important);
|
665 |
endif;
|
666 |
endforeach;
|
667 |
-
$sel_output .= $this->encode_shorthand($shorthand); // . ($important ? ' !important' : '');
|
668 |
-
if ($has_value):
|
669 |
$sel_output .= '}' . LF;
|
670 |
endif;
|
671 |
endif;
|
672 |
endforeach;
|
673 |
-
if ('base' != $query) $sel_output .= '}' . LF;
|
674 |
-
if ($has_selector) $output .= $sel_output;
|
675 |
endforeach;
|
676 |
-
$stylesheet = apply_filters('chld_thm_cfg_target', $this->get_child_target(), $this);
|
677 |
-
if ($stylesheet_verified = $this->is_file_ok($stylesheet, 'write')):
|
678 |
global $wp_filesystem; // this was initialized earlier;
|
679 |
// backup current stylesheet
|
680 |
-
if ($backup && is_file($stylesheet_verified)):
|
681 |
-
$timestamp = date('YmdHis', current_time('timestamp'));
|
682 |
-
$bakfile = preg_replace("/\.css$/", '', $stylesheet_verified) . '-' . $timestamp . '.css';
|
683 |
// don't write new stylesheet if backup fails
|
684 |
-
if (!$wp_filesystem->copy($this->ctc()->fspath($stylesheet_verified), $this->ctc()->fspath($bakfile))) return FALSE;
|
685 |
endif;
|
686 |
// write new stylesheet:
|
687 |
// try direct write first, then wp_filesystem write
|
688 |
// stylesheet must already exist and be writable by web server
|
689 |
-
if (FALSE !== @file_put_contents($stylesheet_verified, $output)): //is_writable($stylesheet_verified) &&
|
690 |
return TRUE;
|
691 |
-
elseif (FALSE !== $wp_filesystem->put_contents($this->ctc()->fspath($stylesheet_verified), $output)):
|
692 |
return TRUE;
|
693 |
endif;
|
694 |
endif;
|
@@ -701,37 +707,37 @@ class ChildThemeConfiguratorCSS {
|
|
701 |
* These are based on commonly used practices and not all vendor prefixed are supported
|
702 |
* TODO: verify this logic against vendor and W3C documentation
|
703 |
*/
|
704 |
-
function add_vendor_rules($rule, $value, &$shorthand, $important = 0) {
|
705 |
$rules = '';
|
706 |
-
if ('filter' == $rule && (FALSE !== strpos($value, 'progid:DXImageTransform.Microsoft.Gradient'))) return;
|
707 |
$importantstr = $important ? ' !important' : '';
|
708 |
-
if (preg_match("/^(margin|padding)\-(top|right|bottom|left)$/", $rule, $matches)):
|
709 |
$shorthand[$matches[1]][$matches[2]] = $value . $importantstr;
|
710 |
return '';
|
711 |
-
elseif (preg_match('/^(' . implode('|', $this->vendorrule) . ')$/', $rule)):
|
712 |
-
foreach(array('moz', 'webkit', 'o') as $prefix):
|
713 |
$rules .= ' -' . $prefix . '-' . $rule . ': ' . $value . $importantstr . ';' . LF;
|
714 |
endforeach;
|
715 |
$rules .= ' ' . $rule . ': ' . $value . $importantstr . ';' . LF;
|
716 |
-
elseif ('background-image' == $rule):
|
717 |
// gradient?
|
718 |
|
719 |
-
if ($gradient = $this->decode_gradient($value)):
|
720 |
// standard gradient
|
721 |
-
foreach(array('moz', 'webkit', 'o', 'ms') as $prefix):
|
722 |
$rules .= ' background-image: -' . $prefix . '-' . 'linear-gradient(' . $gradient['origin'] . ', '
|
723 |
. $gradient['color1'] . ', ' . $gradient['color2'] . ')' . $importantstr . ';' . LF;
|
724 |
endforeach;
|
725 |
// W3C standard gradient
|
726 |
// rotate origin 90 degrees
|
727 |
-
if (preg_match('/(\d+)deg/', $gradient['origin'], $matches)):
|
728 |
-
$org = (90 - $matches[1]) . 'deg';
|
729 |
else:
|
730 |
-
foreach (preg_split("/\s+/", $gradient['origin']) as $dir):
|
731 |
-
$dir = strtolower($dir);
|
732 |
-
$dirs[] = ('top' == $dir ? 'bottom' : ('bottom' == $dir ? 'top' : ('left' == $dir ? 'right' : ('right' == $dir ? 'left' : $dir))));
|
733 |
endforeach;
|
734 |
-
$org = 'to ' . implode(' ', $dirs);
|
735 |
endif;
|
736 |
$rules .= ' background-image: linear-gradient(' . $org . ', '
|
737 |
. $gradient['color1'] . ', ' . $gradient['color2'] . ')' . $importantstr . ';' . LF;
|
@@ -740,16 +746,16 @@ class ChildThemeConfiguratorCSS {
|
|
740 |
// '-webkit-gradient(linear,' .$origin . ', ' . $color1 . ', '. $color2 . ')';
|
741 |
|
742 |
// MS filter gradient
|
743 |
-
$type = (in_array($gradient['origin'], array('left', 'right', '0deg', '180deg')) ? 1 : 0);
|
744 |
-
$color1 = preg_replace("/^#/", '#00', $gradient['color1']);
|
745 |
$rules .= ' filter: progid:DXImageTransform.Microsoft.Gradient(GradientType=' . $type . ', StartColorStr="'
|
746 |
-
. strtoupper($color1) . '", EndColorStr="' . strtoupper($gradient['color2']) . '")' . $importantstr . ';' . LF;
|
747 |
else:
|
748 |
// url or other value
|
749 |
$rules .= ' ' . $rule . ': ' . $value . $importantstr . ';' . LF;
|
750 |
endif;
|
751 |
else:
|
752 |
-
$rule = preg_replace_callback("/\d+/", array($this, 'from_ascii'), $rule);
|
753 |
$rules .= ' ' . $rule . ': ' . $value . $importantstr . ';' . LF;
|
754 |
endif;
|
755 |
return $rules;
|
@@ -760,43 +766,43 @@ class ChildThemeConfiguratorCSS {
|
|
760 |
* parses background shorthand value and returns
|
761 |
* normalized rule/value pairs for each property
|
762 |
*/
|
763 |
-
function normalize_background($value, &$rules, &$values){
|
764 |
-
if (FALSE !== strpos($value, 'gradient')):
|
765 |
// only supporting linear syntax
|
766 |
-
if (preg_match('#(linear\-|Microsoft\.)#', $value)):
|
767 |
$values[] = $value;
|
768 |
$rules[] = 'background-image';
|
769 |
endif;
|
770 |
else:
|
771 |
$regex = '#(url *\([^\)]+\))#';
|
772 |
-
if (preg_match($regex, $value, $matches)) $url = $matches[1];
|
773 |
-
$parts = preg_split($regex, $value);
|
774 |
|
775 |
-
if (count($parts) == 1):
|
776 |
// this is a named color or single hex color or none
|
777 |
-
$part = str_replace(' ', '', $parts[0]);
|
778 |
$rules[] = 'none' == $part ? 'background' : 'background-color';
|
779 |
$values[] = $part;
|
780 |
else:
|
781 |
$rules[] = 'background-image';
|
782 |
$values[] = $url;
|
783 |
-
if (!empty($parts[0]) && '' !== $parts[0]):
|
784 |
$rules[] = 'background-color';
|
785 |
-
$values[] = trim($parts[0]);
|
786 |
endif;
|
787 |
$position = array();
|
788 |
-
foreach(preg_split('/ +/', trim($parts[1])) as $part):
|
789 |
-
if ('' === $part) continue; // empty($part) ||
|
790 |
-
if (FALSE === strpos($part, 'repeat')):
|
791 |
$position[] = $part;
|
792 |
else:
|
793 |
$rules[] = 'background-repeat';
|
794 |
$values[] = $part;
|
795 |
endif;
|
796 |
endforeach;
|
797 |
-
if (count($position)):
|
798 |
$rules[] = 'background-position';
|
799 |
-
$values[] = implode(' ', $position);
|
800 |
endif;
|
801 |
endif;
|
802 |
endif;
|
@@ -807,26 +813,26 @@ class ChildThemeConfiguratorCSS {
|
|
807 |
* parses font shorthand value and returns
|
808 |
* normalized rule/value pairs for each property
|
809 |
*/
|
810 |
-
function normalize_font($value, &$rules, &$values) {
|
811 |
$regex = '#^((\d+|bold|normal) )?((italic|normal) )?(([\d\.]+(px|r?em|%))[\/ ])?(([\d\.]+(px|r?em|%)?) )?(.+)$#is';
|
812 |
-
preg_match($regex, $value, $parts);
|
813 |
-
if (!empty($parts[2])):
|
814 |
$rules[] = 'font-weight';
|
815 |
$values[] = $parts[2];
|
816 |
endif;
|
817 |
-
if (!empty($parts[4])):
|
818 |
$rules[] = 'font-style';
|
819 |
$values[] = $parts[4];
|
820 |
endif;
|
821 |
-
if (!empty($parts[6])):
|
822 |
$rules[] = 'font-size';
|
823 |
$values[] = $parts[6];
|
824 |
endif;
|
825 |
-
if (!empty($parts[9])):
|
826 |
$rules[] = 'line-height';
|
827 |
$values[] = $parts[9];
|
828 |
endif;
|
829 |
-
if (!empty($parts[11])):
|
830 |
$rules[] = 'font-family';
|
831 |
$values[] = $parts[11];
|
832 |
endif;
|
@@ -838,11 +844,11 @@ class ChildThemeConfiguratorCSS {
|
|
838 |
* normalized rule/value pairs for each property
|
839 |
* TODO: reassemble into shorthand when writing CSS file
|
840 |
*/
|
841 |
-
function normalize_margin_padding($rule, $value, &$rules, &$values) {
|
842 |
-
$parts = preg_split("/ +/", trim($value));
|
843 |
-
if (!isset($parts[1])) $parts[1] = $parts[0];
|
844 |
-
if (!isset($parts[2])) $parts[2] = $parts[0];
|
845 |
-
if (!isset($parts[3])) $parts[3] = $parts[1];
|
846 |
$rules[0] = $rule . '-top';
|
847 |
$values[0] = $parts[0];
|
848 |
$rules[1] = $rule . '-right';
|
@@ -853,49 +859,53 @@ class ChildThemeConfiguratorCSS {
|
|
853 |
$values[3] = $parts[3];
|
854 |
}
|
855 |
|
856 |
-
|
|
|
|
|
|
|
|
|
857 |
$rules = '';
|
858 |
$importantstr = ' !important';
|
859 |
-
foreach (array_keys($shorthand) as $key):
|
860 |
$important = array();
|
861 |
$rule = array();
|
862 |
$importantct = 0;
|
863 |
// which sides do we have and are they important?
|
864 |
-
foreach($shorthand[$key] as $side => $val):
|
865 |
$ict = 0;
|
866 |
-
$rule[$side] = trim(preg_replace('/'.$importantstr.'/', '', $val, 1, $ict));
|
867 |
$important[$side] = $ict;
|
868 |
$importantct += $ict;
|
869 |
endforeach;
|
870 |
// shorthand must have 4 explicit values and all must have same priority
|
871 |
-
if (4 == count($rule) && (0 == $importantct || 4 == $importantct )):
|
872 |
// let's try to condense the values into as few as possible, starting with the top value
|
873 |
$parts = array();
|
874 |
$parts[0] = $rule['top'];
|
875 |
// if left is not the same as right, we must use all 4 values
|
876 |
-
if ($rule['left'] !== $rule['right']):
|
877 |
$parts[3] = $rule['left'];
|
878 |
$parts[2] = $rule['bottom'];
|
879 |
$parts[1] = $rule['right'];
|
880 |
endif;
|
881 |
// if top is not the same as bottom, we must use at least 3 values
|
882 |
-
if ($rule['bottom'] !== $rule['top']):
|
883 |
$parts[2] = $rule['bottom'];
|
884 |
$parts[1] = $rule['right'];
|
885 |
endif;
|
886 |
// if top is not the same as right, we must use at least 2 values
|
887 |
-
if ($rule['right'] !== $rule['top']):
|
888 |
$parts[1] = $rule['right'];
|
889 |
endif;
|
890 |
// the order of the sides is critical: top right bottom left
|
891 |
-
ksort($parts);
|
892 |
-
$shorthandstr = implode(' ', $parts);
|
893 |
// if important counter is > 0, it must be == 4, add flag
|
894 |
-
$rules .= ' ' . $key . ': ' . $shorthandstr . ($importantct ? ' ' . $importantstr : '') . ';' . LF;
|
895 |
else:
|
896 |
// otherwise return separate rule for each side
|
897 |
-
foreach ($rule as $side => $value):
|
898 |
-
$rules .= ' ' . $key . '-' . $side . ': ' . $value . ($important[$side] ? $importantstr : '') . ';' . LF;
|
899 |
endforeach;
|
900 |
endif;
|
901 |
endforeach;
|
@@ -908,75 +918,76 @@ class ChildThemeConfiguratorCSS {
|
|
908 |
* Currently only supports two-color linear gradients with no inner stops.
|
909 |
* TODO: legacy webkit? more gradients?
|
910 |
*/
|
911 |
-
function encode_gradient($value) {
|
|
|
912 |
$regex = '#gradient[^\)]*?\((((top|bottom|left|right)?( (top|bottom|left|right))?|\d+deg),)?([^\)]*[\'"]?(\#\w{3,8}|rgba?\([\d, ]+?\)|hsla?\([\d%, ]+?\))( \d+%)?)([^\)]*[\'"]?(\#\w{3,8}|rgba?\([\d, ]+?\)|hsla?\([\d%, ]+?\))( \d+%)?)([^\)]*gradienttype=[\'"]?(\d)[\'"]?)?[^\)]*\)#i';
|
913 |
$param = $parts = array();
|
914 |
-
preg_match($regex, $value, $parts);
|
915 |
-
if (empty($parts[13])):
|
916 |
-
if (empty($parts[2])):
|
917 |
$param[0] = 'top';
|
918 |
else:
|
919 |
-
$param[0] = trim($parts[2]);
|
920 |
endif;
|
921 |
-
if (empty($parts[8])):
|
922 |
$param[2] = '0%';
|
923 |
else:
|
924 |
-
$param[2] = trim($parts[8]);
|
925 |
endif;
|
926 |
-
if (empty($parts[11])):
|
927 |
$param[4] = '100%';
|
928 |
else:
|
929 |
-
$param[4] = trim($parts[11]);
|
930 |
endif;
|
931 |
-
elseif('0' == $parts[13]):
|
932 |
$param[0] = 'top';
|
933 |
$param[2] = '0%';
|
934 |
$param[4] = '100%';
|
935 |
-
elseif ('1' == $parts[13]):
|
936 |
$param[0] = 'left';
|
937 |
$param[2] = '0%';
|
938 |
$param[4] = '100%';
|
939 |
endif;
|
940 |
-
if (isset($parts[7]) && isset($parts[10])):
|
941 |
$param[1] = $parts[7];
|
942 |
$param[3] = $parts[10];
|
943 |
-
ksort($param);
|
944 |
-
return implode(':', $param);
|
945 |
else: return $value;
|
946 |
endif;
|
947 |
}
|
948 |
|
949 |
/*
|
950 |
* decode_border
|
951 |
-
* De-normalize CTC border syntax into
|
952 |
*/
|
953 |
-
function decode_border($value) {
|
954 |
-
if (preg_match('#^(0|none)#i', $value)):
|
955 |
$parts[0] = $value;
|
956 |
$parts[1] = $parts[2] = '';
|
957 |
else:
|
958 |
-
$parts = preg_split('#\s+#', $value, 3);
|
959 |
endif;
|
960 |
return array(
|
961 |
-
'width' => empty($parts[0])?''
|
962 |
-
'style' => empty($parts[1])?''
|
963 |
-
'color' => empty($parts[2])?''
|
964 |
);
|
965 |
}
|
966 |
|
967 |
/*
|
968 |
* decode_gradient
|
969 |
-
* Decode CTC gradient syntax into
|
970 |
*/
|
971 |
-
function decode_gradient($value) {
|
972 |
-
$parts = explode(':', $value, 5);
|
973 |
-
if (!preg_match('#(url|none)#i', $value) && 5 == count($parts)):
|
974 |
return array(
|
975 |
-
'origin' => empty($parts[0]) ? '' : $parts[0],
|
976 |
-
'color1' => empty($parts[1]) ? '' : $parts[1],
|
977 |
-
'stop1' => empty($parts[2]) ? '' : $parts[2],
|
978 |
-
'color2' => empty($parts[3]) ? '' : $parts[3],
|
979 |
-
'stop2' => empty($parts[4]) ? '' : $parts[4],
|
980 |
);
|
981 |
endif;
|
982 |
return FALSE;
|
@@ -986,13 +997,13 @@ class ChildThemeConfiguratorCSS {
|
|
986 |
* denorm_rule_val
|
987 |
* Return array of unique values corresponding to specific rule
|
988 |
*/
|
989 |
-
function denorm_rule_val($ruleid) {
|
990 |
$rule_sel_arr = array();
|
991 |
-
$val_arr = array_flip($this->dict_val);
|
992 |
-
foreach ($this->val_ndx as $selid => $rules):
|
993 |
-
if (!isset($rules[$ruleid])) continue;
|
994 |
-
foreach ($rules[$ruleid] as $theme => $val):
|
995 |
-
if (!isset($val_arr[$val]) || '' === $val_arr[$val]) continue;
|
996 |
$rule_sel_arr[$val] = $val_arr[$val];
|
997 |
endforeach;
|
998 |
endforeach;
|
@@ -1004,15 +1015,15 @@ class ChildThemeConfiguratorCSS {
|
|
1004 |
* Return array of queries, selectors, rules, and values corresponding to
|
1005 |
* specific rule/value combo grouped by query, selector
|
1006 |
*/
|
1007 |
-
function denorm_val_query($valid, $rule) {
|
1008 |
$value_query_arr = array();
|
1009 |
-
foreach ($this->val_ndx as $qsid => $rules):
|
1010 |
-
foreach ($rules as $ruleid => $values):
|
1011 |
-
if ($ruleid != $this->dict_rule[$rule]) continue;
|
1012 |
-
foreach ($values as $name => $val):
|
1013 |
-
if ('i' == $name || $val != $valid) continue;
|
1014 |
-
$selarr = $this->denorm_query_sel($qsid);
|
1015 |
-
$valarr = $this->denorm_sel_val($qsid);
|
1016 |
$value_query_arr[$rule][$selarr['query']][$qsid] = $valarr;
|
1017 |
endforeach;
|
1018 |
endforeach;
|
@@ -1024,10 +1035,10 @@ class ChildThemeConfiguratorCSS {
|
|
1024 |
* denorm_query_sel
|
1025 |
* Return id, query and selector values of a specific qsid (query-selector ID)
|
1026 |
*/
|
1027 |
-
function denorm_query_sel($qsid) {
|
1028 |
-
$queryarr = array_flip($this->dict_query);
|
1029 |
-
$selarr = array_flip($this->dict_sel);
|
1030 |
-
$this->dict_seq[$qsid] = isset($this->dict_seq[$qsid]) ? $this->dict_seq[$qsid] : $qsid;
|
1031 |
return array(
|
1032 |
'id' => $qsid,
|
1033 |
'query' => $queryarr[$this->dict_qs[$qsid]['q']],
|
@@ -1041,16 +1052,16 @@ class ChildThemeConfiguratorCSS {
|
|
1041 |
* Return array of rules, and values matching specific qsid (query-selector ID)
|
1042 |
* grouped by query, selector
|
1043 |
*/
|
1044 |
-
function denorm_sel_val($qsid) {
|
1045 |
-
$selarr = $this->denorm_query_sel($qsid);
|
1046 |
-
$valarr = array_flip($this->dict_val);
|
1047 |
-
$rulearr = array_flip($this->dict_rule);
|
1048 |
-
if (isset($this->val_ndx[$qsid]) && is_array($this->val_ndx[$qsid])):
|
1049 |
-
foreach ($this->val_ndx[$qsid] as $ruleid => $values):
|
1050 |
-
foreach ($values as $name => $val):
|
1051 |
-
if ('i_parnt' == $name || 'i_child' == $name):
|
1052 |
-
$selarr['value'][$rulearr[$ruleid]][$name] = (empty($val) ? 0 : 1);
|
1053 |
-
elseif (!isset($valarr[$val]) || '' === $valarr[$val]):
|
1054 |
continue;
|
1055 |
else:
|
1056 |
$selarr['value'][$rulearr[$ruleid]][$name] = $valarr[$val];
|
@@ -1066,16 +1077,16 @@ class ChildThemeConfiguratorCSS {
|
|
1066 |
* denorm_sel_ndx
|
1067 |
* Return denormalized array containing query and selector heirarchy
|
1068 |
*/
|
1069 |
-
function denorm_sel_ndx($query =
|
1070 |
$sel_ndx_norm = array();
|
1071 |
-
$queryarr = array_flip($this->dict_query);
|
1072 |
-
$selarr = array_flip($this->dict_sel);
|
1073 |
-
foreach($this->sel_ndx as $queryid => $sel):
|
1074 |
-
foreach($sel as $selid => $qsid):
|
1075 |
$sel_ndx_norm[$queryarr[$queryid]][$selarr[$selid]] = $qsid;
|
1076 |
endforeach;
|
1077 |
endforeach;
|
1078 |
-
return empty($query) ? $sel_ndx_norm : $sel_ndx_norm[$query];
|
1079 |
}
|
1080 |
|
1081 |
/*
|
@@ -1083,9 +1094,9 @@ class ChildThemeConfiguratorCSS {
|
|
1083 |
* Strip important flag from value ref and return boolean
|
1084 |
* Value is updated because it is a ref
|
1085 |
*/
|
1086 |
-
function is_important(&$value) {
|
1087 |
$important = 0;
|
1088 |
-
$value = trim(str_ireplace('!important', '', $value, $important));
|
1089 |
return $important;
|
1090 |
}
|
1091 |
|
@@ -1099,29 +1110,29 @@ class ChildThemeConfiguratorCSS {
|
|
1099 |
*/
|
1100 |
function sort_queries() {
|
1101 |
$queries = array();
|
1102 |
-
$queryarr = array_flip($this->dict_query);
|
1103 |
-
foreach (array_keys($this->sel_ndx) as $queryid):
|
1104 |
$query = $queryarr[$queryid];
|
1105 |
-
if ('base' == $query):
|
1106 |
$queries['base'] = -999999;
|
1107 |
continue;
|
1108 |
endif;
|
1109 |
-
if (preg_match("/((min|max)(\-device)?\-width)\s*:\s*(\d+)/", $query, $matches)):
|
1110 |
$queries[$query] = 'min-width' == $matches[1] ? $matches[4] : -$matches[4];
|
1111 |
else:
|
1112 |
$queries[$query] = $queryid - 10000;
|
1113 |
endif;
|
1114 |
endforeach;
|
1115 |
-
asort($queries);
|
1116 |
return $queries;
|
1117 |
}
|
1118 |
|
1119 |
// sort selectors based on dict_seq if exists, otherwise qsid
|
1120 |
-
function cmp_seq($a, $b) {
|
1121 |
-
$cmpa = isset($this->dict_seq[$a])
|
1122 |
-
$cmpb = isset($this->dict_seq[$b])
|
1123 |
-
if ($cmpa == $cmpb) return 0;
|
1124 |
-
return ($cmpa < $cmpb) ? -1 : 1;
|
1125 |
}
|
1126 |
|
1127 |
/*
|
@@ -1130,52 +1141,54 @@ class ChildThemeConfiguratorCSS {
|
|
1130 |
* flattens to array
|
1131 |
* and stringifies NULLs
|
1132 |
*/
|
1133 |
-
function obj_to_utf8($data) {
|
1134 |
|
1135 |
-
if (is_object($data)) {
|
1136 |
-
$data = get_object_vars($data);
|
1137 |
}
|
1138 |
-
if (is_array($data)) {
|
1139 |
-
return array_map(array(&$this, __FUNCTION__), $data);
|
1140 |
}
|
1141 |
else {
|
1142 |
-
return is_null( $data ) ? '' : utf8_encode($data);
|
1143 |
}
|
1144 |
}
|
1145 |
-
|
1146 |
-
function to_ascii($matches) {
|
1147 |
-
return ord($matches[0]);
|
1148 |
}
|
1149 |
-
|
1150 |
-
function from_ascii($matches) {
|
1151 |
-
return chr($matches[0]);
|
1152 |
}
|
1153 |
|
1154 |
/* is_file_ok
|
1155 |
* verify file exists and is in valid location
|
1156 |
*/
|
1157 |
-
function is_file_ok($stylesheet, $permission = 'read') {
|
1158 |
// remove any ../ manipulations
|
1159 |
-
$stylesheet = preg_replace("%\.\./%", '/', $stylesheet);
|
1160 |
-
if ('read' == $permission && !is_file($stylesheet)) return FALSE;
|
1161 |
-
if ('search' == $permission && !is_dir($stylesheet)) return FALSE;
|
1162 |
// sanity check for php files
|
1163 |
-
//if (!preg_match('%' . preg_quote($ext) . '$%', $stylesheet)) return FALSE;
|
1164 |
// check if in themes dir;
|
1165 |
-
if (preg_match('%^' . preg_quote(get_theme_root()) . '%', $stylesheet)) return $stylesheet;
|
1166 |
// check if in plugins dir
|
1167 |
-
if (preg_match('%^' . preg_quote(WP_PLUGIN_DIR) . '%', $stylesheet)) return $stylesheet;
|
1168 |
return FALSE;
|
1169 |
}
|
1170 |
-
|
1171 |
-
|
1172 |
-
|
|
|
|
|
1173 |
$value = preg_replace( "/#([0-9A-F])\\1([0-9A-F])\\2([0-9A-F])\\3/i", "#$1$2$3", $value );
|
1174 |
return $value;
|
1175 |
}
|
1176 |
-
|
1177 |
-
function tolower($matches) {
|
1178 |
-
return '#' . strtolower($matches[1]);
|
1179 |
}
|
1180 |
}
|
1181 |
?>
|
1 |
<?php
|
2 |
// Exit if accessed directly
|
3 |
+
if ( !defined( 'ABSPATH' ) ) exit;
|
4 |
|
5 |
/*
|
6 |
Class: ChildThemeConfiguratorCSS
|
7 |
Plugin URI: http://www.lilaeamedia.com/plugins/child-theme-configurator/
|
8 |
Description: Handles all CSS output, parsing, normalization
|
9 |
+
Version: 1.6.3
|
10 |
Author: Lilaea Media
|
11 |
Author URI: http://www.lilaeamedia.com/
|
12 |
Text Domain: chld_thm_cfg
|
13 |
Domain Path: /lang
|
14 |
License: GPLv2
|
15 |
+
Copyright (C) 2014-2015 Lilaea Media
|
16 |
*/
|
17 |
class ChildThemeConfiguratorCSS {
|
18 |
// data dictionaries
|
104 |
$this->sel_ndx = array();
|
105 |
$this->val_ndx = array();
|
106 |
$this->parntss = array();
|
107 |
+
$this->imports = array( 'child' => array(), 'parnt' => array() );
|
108 |
}
|
109 |
+
// helper function to globalize ctc object
|
110 |
function ctc() {
|
111 |
global $chld_thm_cfg;
|
112 |
return $chld_thm_cfg;
|
113 |
}
|
114 |
+
// loads current ctc config data into local memory
|
115 |
function read_config() {
|
116 |
|
117 |
+
if ( $configarray = get_option( CHLD_THM_CFG_OPTIONS . '_configvars' ) ):
|
118 |
+
foreach ( $this->configvars as $configkey )
|
119 |
+
if ( isset( $configarray[$configkey] ) )
|
120 |
$this->{$configkey} = $configarray[$configkey];
|
121 |
+
foreach ( $this->dicts as $configkey ):
|
122 |
+
if ( $configarray = get_option( CHLD_THM_CFG_OPTIONS . '_' . $configkey ) )
|
123 |
$this->{$configkey} = $configarray;
|
124 |
endforeach;
|
125 |
else:
|
126 |
return FALSE;
|
127 |
endif;
|
128 |
}
|
129 |
+
// writes ctc config data to options api
|
130 |
function save_config() {
|
131 |
|
132 |
$configarray = array();
|
133 |
+
foreach ( $this->configvars as $configkey )
|
134 |
$configarray[$configkey] = $this->{$configkey};
|
135 |
+
update_option( CHLD_THM_CFG_OPTIONS . '_configvars', $configarray );
|
136 |
+
foreach ( $this->dicts as $configkey )
|
137 |
+
update_option( CHLD_THM_CFG_OPTIONS . '_' . $configkey, $this->{$configkey} );
|
138 |
// remove pre 1.5.4 options
|
139 |
+
delete_option( CHLD_THM_CFG_OPTIONS );
|
140 |
}
|
141 |
/*
|
142 |
* get_prop
|
143 |
+
* Getter interface (data sliced different ways depending on objname )
|
144 |
*/
|
145 |
+
function get_prop( $objname, $params = NULL ) {
|
146 |
+
switch ( $objname ):
|
147 |
case 'imports':
|
148 |
+
return $this->obj_to_utf8( is_array( $this->imports['child'] ) ? ( current( $this->imports['child'] ) == 1 ? array_keys( $this->imports['child'] ) : array_keys( array_flip( $this->imports['child'] ) ) ) : array() );
|
149 |
case 'sel_ndx':
|
150 |
+
return $this->obj_to_utf8( $this->denorm_sel_ndx( empty( $params['key'] ) ? NULL : $params['key'] ) );
|
151 |
case 'rule_val':
|
152 |
+
return empty( $params['key'] ) ? array() : $this->denorm_rule_val( $params['key'] );
|
153 |
case 'val_qry':
|
154 |
+
if ( isset( $params['rule'] ) && isset( $this->dict_rule[$params['rule']] ) ):
|
155 |
+
return empty( $params['key'] ) ?
|
156 |
+
array() : $this->denorm_val_query( $params['key'], $params['rule'] );
|
157 |
endif;
|
158 |
case 'sel_val':
|
159 |
+
return empty( $params['key'] ) ?
|
160 |
+
array() : $this->denorm_sel_val( $params['key'] );
|
161 |
case 'rule':
|
162 |
+
return $this->obj_to_utf8( array_flip( $this->dict_rule ) );
|
163 |
case 'child':
|
164 |
return $this->child;
|
165 |
case 'parnt':
|
166 |
return $this->parnt;
|
167 |
case 'parntss':
|
168 |
+
return isset( $this->parntss ) ? $this->parntss : array();
|
169 |
case 'configtype':
|
170 |
return $this->configtype;
|
171 |
case 'child_name':
|
176 |
return $this->child_version;
|
177 |
case 'preview':
|
178 |
$this->styles = '';
|
179 |
+
if ( empty( $params['key'] ) || 'child' == $params['key'] ):
|
180 |
+
$this->read_stylesheet( 'child' );
|
181 |
else:
|
182 |
+
if ( isset( $this->parntss ) ):
|
183 |
+
foreach ( $this->parntss as $template ):
|
184 |
$this->styles .= '/*** BEGIN ' . $template . ' ***/' . LF;
|
185 |
+
$this->read_stylesheet( 'parnt', $template );
|
186 |
$this->styles .= '/*** END ' . $template . ' ***/' . LF;
|
187 |
endforeach;
|
188 |
endif;
|
189 |
$this->styles .= '/*** BEGIN style.css ***/' . LF;
|
190 |
+
$this->read_stylesheet( 'parnt' );
|
191 |
$this->styles .= '/*** END style.css ***/' . LF;
|
192 |
endif;
|
193 |
$this->normalize_css();
|
200 |
* set_prop
|
201 |
* Setter interface (scalar values only)
|
202 |
*/
|
203 |
+
function set_prop( $prop, $value ) {
|
204 |
+
if ( is_scalar( $this->{$prop} ) )
|
205 |
$this->{$prop} = $value;
|
206 |
else return FALSE;
|
207 |
}
|
208 |
+
// formats css string for accurate parsing
|
209 |
function normalize_css() {
|
210 |
+
if ( preg_match( "/(\}[\w\#\.]|; *\})/", $this->styles ) ): // prettify compressed CSS
|
211 |
+
$this->styles = preg_replace( "/\*\/\s*/s", "*/\n", $this->styles ); // end comment
|
212 |
+
$this->styles = preg_replace( "/\{\s*/s", " {\n ", $this->styles ); // open brace
|
213 |
+
$this->styles = preg_replace( "/;\s*/s", ";\n ", $this->styles ); // semicolon
|
214 |
+
$this->styles = preg_replace( "/\s*\}\s*/s", "\n}\n", $this->styles ); // close brace
|
215 |
endif;
|
216 |
}
|
217 |
+
// creates header comments for stylesheet
|
218 |
function get_css_header() {
|
219 |
+
$parnt = $this->get_prop( 'parnt' );
|
220 |
return '/*' . LF
|
221 |
+
. 'Theme Name: ' . $this->get_prop( 'child_name' ) . LF
|
222 |
. 'Template: ' . $parnt . LF
|
223 |
+
. 'Author: ' . $this->get_prop( 'author' ). LF
|
224 |
+
. 'Version: ' . $this->get_prop( 'version' ) . LF
|
225 |
+
. 'Updated: ' . current_time( 'mysql' ) . LF
|
226 |
. '*/' . LF . LF
|
227 |
. '@charset "UTF-8";' . LF . LF
|
228 |
+
. ( 'import' == $this->enqueue ? '@import url(\'../' . $parnt . '/style.css\');' . LF : '' );
|
229 |
}
|
230 |
+
// formats file path for child theme file
|
231 |
+
function get_child_target( $file = 'style.css' ) {
|
232 |
+
return trailingslashit( get_theme_root() ) . trailingslashit( $this->get_prop( 'child' ) ) . $file;
|
233 |
}
|
234 |
+
// formats file path for parent theme file
|
235 |
+
function get_parent_source( $file = 'style.css' ) {
|
236 |
+
return trailingslashit( get_theme_root() ) . trailingslashit( $this->get_prop( 'parnt' ) ) . $file;
|
237 |
}
|
238 |
|
239 |
/*
|
240 |
* update_arrays
|
241 |
* accepts CSS properties as raw strings and normilizes into
|
242 |
* CTC object arrays, creating update cache in the process.
|
243 |
+
* Update cache is returned to UI via AJAX to refresh page.
|
244 |
*/
|
245 |
+
function update_arrays( $template, $query, $sel, $rule = NULL, $value = NULL, $important = 0, $seq = NULL ) {
|
246 |
|
247 |
// normalize selector styling
|
248 |
+
$sel = implode( ', ', preg_split( '#\s*,\s*#s', trim( $sel ) ) );
|
249 |
// add selector and query to index
|
250 |
+
if ( !isset( $this->dict_query[$query] ) ) $this->dict_query[$query] = ++$this->querykey;
|
251 |
+
if ( !isset( $this->dict_sel[$sel] ) ) $this->dict_sel[$sel] = ++$this->selkey;
|
252 |
+
if ( !isset( $this->sel_ndx[$this->dict_query[$query]][$this->dict_sel[$sel]] ) ):
|
253 |
// increment key number
|
254 |
$this->sel_ndx[$this->dict_query[$query]][$this->dict_sel[$sel]] = ++$this->qskey;
|
255 |
|
257 |
$this->dict_qs[$this->qskey]['q'] = $this->dict_query[$query];
|
258 |
// tell the UI to update a single cached query/selector lookup by passing 'qsid' as the key
|
259 |
// (normally the entire array is replaced):
|
260 |
+
if ( $this->ctc()->cache_updates )
|
261 |
$this->ctc()->updates[] = array(
|
262 |
'obj' => 'sel_ndx',
|
263 |
'key' => 'qsid',
|
269 |
);
|
270 |
endif;
|
271 |
// update sequence for this selector if this is a later instance to keep cascade priority
|
272 |
+
if ( !isset( $this->dict_seq[$this->qskey] ) )
|
273 |
$this->dict_seq[$this->qskey] = $this->qskey;
|
274 |
// set data and value
|
275 |
+
if ( $rule ):
|
276 |
+
if ( !isset( $this->dict_rule[$rule] ) ):
|
277 |
$this->dict_rule[$rule] = ++$this->rulekey;
|
278 |
// tell the UI to update a single cached rule:
|
279 |
+
if ( $this->ctc()->cache_updates ):
|
280 |
$this->ctc()->updates[] = array(
|
281 |
'obj' => 'rule',
|
282 |
'key' => $this->rulekey,
|
286 |
endif;
|
287 |
$qsid = $this->sel_ndx[$this->dict_query[$query]][$this->dict_sel[$sel]];
|
288 |
$ruleid = $this->dict_rule[$rule];
|
289 |
+
if ( !isset( $this->dict_val[$value] ) ):
|
290 |
$this->dict_val[$value] = ++$this->valkey;
|
291 |
endif;
|
292 |
$this->val_ndx[$qsid][$ruleid][$template] = $this->dict_val[$value];
|
293 |
// set the important flag for this value
|
294 |
$this->val_ndx[$qsid][$ruleid]['i_' . $template] = $important;
|
295 |
// tell the UI to add a single cached query/selector data array:
|
296 |
+
if ( $this->ctc()->cache_updates ):
|
297 |
$updatearr = array(
|
298 |
'obj' => 'sel_val',
|
299 |
'key' => $qsid,
|
300 |
+
'data' => $this->denorm_sel_val( $qsid ),
|
301 |
);
|
302 |
$this->ctc()->updates[] = $updatearr;
|
303 |
endif;
|
304 |
+
if ( isset( $seq ) ): // this is a renamed selector
|
305 |
$this->dict_seq[$qsid] = $seq;
|
306 |
+
if ( $this->ctc()->cache_updates ):
|
307 |
$this->ctc()->updates[] = array(
|
308 |
'obj' => 'rewrite',
|
309 |
'key' => $qsid,
|
313 |
endif;
|
314 |
endif;
|
315 |
}
|
316 |
+
// loads raw css file into local memory
|
317 |
+
function read_stylesheet( $template = 'child', $file = 'style.css' ) {
|
318 |
|
319 |
// these conditions support revert/restore option in 1.6.0+
|
320 |
+
if ( 'all' == $file ) return;
|
321 |
+
elseif ( '' == $file ) $file = 'style.css';
|
322 |
// end revert/restore conditions
|
323 |
|
324 |
+
$source = $this->get_prop( $template );
|
325 |
+
$configtype = $this->get_prop( 'configtype' );
|
326 |
+
if ( empty( $source ) || !is_scalar( $source ) ) return FALSE;
|
327 |
$themedir = get_theme_root() . '/' . $source;
|
328 |
+
$stylesheet = apply_filters( 'chld_thm_cfg_' . $template, $themedir . '/' . $file , $this );
|
329 |
|
330 |
// read stylesheet
|
331 |
+
if ( $stylesheet_verified = $this->is_file_ok( $stylesheet, 'read' ) ):
|
332 |
+
$import_url = preg_replace( '%^' . preg_quote( $themedir ) . '/%', '', $stylesheet_verified );
|
333 |
+
$this->styles .= @file_get_contents( $stylesheet_verified ) . "\n";
|
334 |
endif;
|
335 |
}
|
336 |
+
/* recurse_directory
|
337 |
+
* searches filesystem for valid files based on parameters and returns array of filepaths.
|
338 |
+
* Because it requires logic specific to CTC, core WP recurse function is not used.
|
339 |
+
*/
|
340 |
function recurse_directory( $rootdir, $ext = 'css', $all = FALSE ) {
|
341 |
if ( !$this->is_file_ok( $rootdir, 'search' ) ) return array(); // make sure we are only recursing theme and plugin files
|
342 |
$files = array();
|
343 |
+
$dirs = array( $rootdir );
|
344 |
$loops = 0;
|
345 |
if ( 'img' == $ext ):
|
346 |
|
347 |
+
$ext = '(' . implode( '|', array_keys( $this->ctc()->imgmimes ) ) . ')';
|
348 |
endif;
|
349 |
+
while( count( $dirs ) && $loops < CHLD_THM_CFG_MAX_RECURSE_LOOPS ):
|
350 |
$loops++;
|
351 |
+
$dir = array_shift( $dirs );
|
352 |
+
if ( $handle = opendir( $dir ) ):
|
353 |
+
while ( FALSE !== ( $file = readdir( $handle ) ) ):
|
354 |
+
if ( preg_match( "/^\./", $file ) ) continue;
|
355 |
+
$filepath = trailingslashit( $dir ) . $file;
|
356 |
+
if ( is_dir( $filepath ) ):
|
357 |
+
array_unshift( $dirs, $filepath );
|
358 |
+
if ( $all ):
|
359 |
$files[] = $filepath;
|
360 |
endif;
|
361 |
+
elseif ( is_file( $filepath ) && ( $all || preg_match( "/\.".$ext."$/i", $filepath ) ) ):
|
362 |
$files[] = $filepath;
|
363 |
endif;
|
364 |
endwhile;
|
365 |
+
closedir( $handle );
|
366 |
endif;
|
367 |
endwhile;
|
368 |
return $files;
|
369 |
}
|
370 |
+
// allows images to be used between parent and child themes
|
371 |
+
function convert_parent_rel_url_to_abs_url( $url ) {
|
372 |
+
$source = $this->get_prop( 'parnt' );
|
373 |
$spliton = '%[/\\\\]%';
|
374 |
+
$dirname = dirname( $url );
|
375 |
+
$dirs = preg_split( $spliton, $dirname );
|
376 |
$dds = '';
|
377 |
$themeuri = get_theme_root_uri();
|
378 |
+
while ( count( $dirs ) ):
|
379 |
+
$thisdir = array_pop( $dirs );
|
380 |
+
$upone = implode( '/', $dirs );
|
381 |
$dds .= '\.\.\/';
|
382 |
$regex = '%url\([\'" ]*' . $dds . '(.+?)[\'" ]*\)%';
|
383 |
+
$fullurl = $themeuri . '/' . $source . '/' . $upone . ( '' == $upone ? '' : '/' );
|
384 |
+
$this->styles = preg_replace( $regex, "url(" . $fullurl . "$1)", $this->styles );
|
385 |
endwhile;
|
386 |
}
|
387 |
/*
|
390 |
*/
|
391 |
function parse_post_data() {
|
392 |
$this->cache_updates = TRUE;
|
393 |
+
if ( isset( $_POST['ctc_new_selectors'] ) ):
|
394 |
+
$this->styles = $this->parse_css_input( LF . $_POST['ctc_new_selectors'] );
|
395 |
+
$this->parse_css( 'child',
|
396 |
+
( isset( $_POST['ctc_sel_ovrd_query'] )?trim( $_POST['ctc_sel_ovrd_query'] ):NULL ), FALSE );
|
397 |
+
elseif ( isset( $_POST['ctc_child_imports'] ) ):
|
398 |
$this->imports['child'] = array();
|
399 |
+
$this->styles = $this->parse_css_input( $_POST['ctc_child_imports'] );
|
400 |
+
$this->parse_css( 'child' );
|
401 |
else:
|
402 |
+
$newselector = isset( $_POST['ctc_rewrite_selector'] ) ? $this->sanitize( $this->parse_css_input( $_POST['ctc_rewrite_selector'] ) ) : NULL;
|
403 |
// set the custom sequence value
|
404 |
+
foreach ( preg_grep( '#^ctc_ovrd_child_seq_#', array_keys( $_POST ) ) as $post_key ):
|
405 |
+
if ( preg_match( '#^ctc_ovrd_child_seq_(\d+)$#', $post_key, $matches ) ):
|
406 |
$qsid = $matches[1];
|
407 |
+
$this->dict_seq[$qsid] = intval( $_POST[$post_key] );
|
408 |
endif;
|
409 |
endforeach;
|
410 |
$parts = array();
|
411 |
+
foreach ( preg_grep( '#^ctc_(ovrd|\d+)_child#', array_keys( $_POST ) ) as $post_key ):
|
412 |
+
if ( preg_match( '#^ctc_(ovrd|\d+)_child_([\w\-]+?)_(\d+?)(_(.+))?$#', $post_key, $matches ) ):
|
413 |
$valid = $matches[1];
|
414 |
$rule = $matches[2];
|
415 |
+
if ( NULL == $rule || !isset( $this->dict_rule[$rule] ) ) continue;
|
416 |
$ruleid = $this->dict_rule[$rule];
|
417 |
$qsid = $matches[3];
|
418 |
+
$value = $this->normalize_color( $this->sanitize( $this->parse_css_input( $_POST[$post_key] ) ) );
|
419 |
+
$important = $this->is_important( $value );
|
420 |
+
if ( !empty( $_POST['ctc_' . $valid . '_child_' . $rule . '_i_' . $qsid] ) ) $important = 1;
|
421 |
|
422 |
+
$selarr = $this->denorm_query_sel( $qsid );
|
423 |
+
if ( !empty( $matches[5] ) ):
|
424 |
$parts[$qsid][$rule][$matches[5]] = $value;
|
425 |
$parts[$qsid][$rule]['important'] = $important;
|
426 |
$parts[$qsid][$rule]['query'] = $selarr['query'];
|
427 |
$parts[$qsid][$rule]['selector'] = $selarr['selector'];
|
428 |
else:
|
429 |
+
if ( $newselector && $newselector != $selarr['selector'] ):
|
430 |
// If this is a renamed selector, add new selector to array
|
431 |
// and clear original child selector values.
|
432 |
// Passing the sequence in the last argument serves two purposes:
|
433 |
// 1. sets sequence for new renamed selector.
|
434 |
// 2. tells the update_arrays function to flag this as a
|
435 |
// renamed selector to pass back in result array.
|
436 |
+
$this->update_arrays( 'child', $selarr['query'], $newselector,
|
437 |
+
$rule, trim( $value ), $important, $this->dict_seq[$qsid] );
|
438 |
+
$this->update_arrays( 'child', $selarr['query'], $selarr['selector'], $rule, '' );
|
439 |
else:
|
440 |
// Otherwise, just update with the new values:
|
441 |
+
$this->update_arrays( 'child', $selarr['query'], $selarr['selector'],
|
442 |
+
$rule, trim( $value ), $important );
|
443 |
endif;
|
444 |
endif;
|
445 |
endif;
|
446 |
endforeach;
|
447 |
+
foreach ( $parts as $qsid => $rule_arr ):
|
448 |
+
foreach ( $rule_arr as $rule => $rule_part ):
|
449 |
+
if ( 'background' == $rule ):
|
450 |
$value = $rule_part['background_url'];
|
451 |
+
elseif ( 'background-image' == $rule ):
|
452 |
+
if ( empty( $rule_part['background_url'] ) ):
|
453 |
+
if ( empty( $rule_part['background_color2'] ) ):
|
454 |
$value = '';
|
455 |
else:
|
456 |
+
$value = implode( ':', array(
|
457 |
$rule_part['background_origin'],
|
458 |
$rule_part['background_color1'], '0%',
|
459 |
$rule_part['background_color2'], '100%'
|
460 |
+
) );
|
461 |
endif;
|
462 |
else:
|
463 |
$value = $rule_part['background_url'];
|
464 |
endif;
|
465 |
+
elseif ( preg_match( '#^border(\-(top|right|bottom|left))?$#', $rule ) ):
|
466 |
+
$value = implode( ' ', array(
|
467 |
$rule_part['border_width'],
|
468 |
$rule_part['border_style'],
|
469 |
$rule_part['border_color']
|
470 |
+
) );
|
471 |
else:
|
472 |
$value = '';
|
473 |
endif;
|
474 |
+
if ( $newselector && $newselector != $rule_part['selector'] ):
|
475 |
+
$this->update_arrays( 'child', $rule_part['query'], $newselector,
|
476 |
+
$rule, trim( $value ), $rule_part['important'], $this->dict_seq[$qsid] );
|
477 |
+
$this->update_arrays( 'child', $rule_part['query'], $rule_part['selector'], $rule, '' );
|
478 |
else:
|
479 |
+
$this->update_arrays( 'child', $rule_part['query'], $rule_part['selector'],
|
480 |
+
$rule, trim( $value ), $rule_part['important'] );
|
481 |
endif;
|
482 |
endforeach;
|
483 |
endforeach;
|
489 |
* Normalize raw user CSS input so that the parser can read it.
|
490 |
* TODO: this is a stub for future use
|
491 |
*/
|
492 |
+
function parse_css_input( $styles ) {
|
493 |
+
return $this->repl_octal( stripslashes( $this->esc_octal( $styles ) ) );
|
494 |
}
|
495 |
+
// strips non printables and potential commands
|
496 |
+
function sanitize( $styles ) {
|
497 |
+
return sanitize_text_field( preg_replace( '/[^[:print:]]/', '', $styles ) );
|
498 |
}
|
499 |
+
// escapes octal values in input to allow for specific ascii strings in content rule
|
500 |
+
function esc_octal( $styles ){
|
501 |
+
return preg_replace( "#(['\"])\\\\([0-9a-f]{4})(['\"])#i", "$1##bs##$2$3", $styles );
|
502 |
}
|
503 |
+
// unescapes octal values for writing specific ascii strings in content rule
|
504 |
+
function repl_octal( $styles ) {
|
505 |
+
return str_replace( "##bs##", "\\", $styles );
|
506 |
}
|
507 |
/*
|
508 |
* parse_css_file
|
509 |
* reads stylesheet to get WordPress meta data and passes rest to parse_css
|
510 |
*/
|
511 |
+
function parse_css_file( $template, $file = 'style.css' ) {
|
512 |
|
513 |
$this->ctc()->cache_updates = FALSE;
|
514 |
$this->styles = ''; // reset styles
|
515 |
+
$this->read_stylesheet( $template, $file );
|
516 |
// get theme name
|
517 |
$regex = '#Theme Name:\s*(.+?)\n#i';
|
518 |
+
preg_match( $regex, $this->styles, $matches );
|
519 |
+
$child_name = $this->get_prop( 'child_name' );
|
520 |
+
if ( !empty( $matches[1] ) && 'child' == $template && empty( $child_name ) ) $this->set_prop( 'child_name', $matches[1] );
|
521 |
+
$this->parse_css( $template );
|
522 |
}
|
523 |
|
524 |
/*
|
525 |
* parse_css
|
526 |
+
* Accepts raw CSS as text and parses into individual properties.
|
527 |
*/
|
528 |
+
function parse_css( $template, $basequery = NULL, $parse_imports = TRUE ) {
|
529 |
+
if ( FALSE === strpos( $basequery, '@' ) ):
|
530 |
$basequery = 'base';
|
531 |
endif;
|
532 |
$ruleset = array();
|
533 |
// ignore commented code
|
534 |
+
$this->styles = preg_replace( '#\/\*.*?\*\/#s', '', $this->styles );
|
535 |
// space brace to ensure correct matching
|
536 |
+
$this->styles = preg_replace( '#(\{\s*)#', "$1\n", $this->styles );
|
537 |
// get all imports
|
538 |
+
if ( $parse_imports ):
|
539 |
|
540 |
$regex = '#(\@import.+?);#';
|
541 |
+
preg_match_all( $regex, $this->styles, $matches );
|
542 |
+
foreach ( preg_grep( '#' . $this->get_prop( 'parnt' ) . '\/style\.css#', $matches[1], PREG_GREP_INVERT ) as $import )
|
543 |
$this->imports[$template][$import] = 1;
|
544 |
+
if ( $this->ctc()->cache_updates ):
|
545 |
$this->ctc()->updates[] = array(
|
546 |
'obj' => 'imports',
|
547 |
+
'data' => array_keys( $this->imports[$template] ),
|
548 |
);
|
549 |
endif;
|
550 |
endif;
|
551 |
// break into @ segments
|
552 |
+
foreach ( array(
|
553 |
'#(\@media[^\{]+?)\{(\s*?)\}#', // get an placehoder (empty) media queries
|
554 |
'#(\@media[^\{]+?)\{(.*?\})?\s*?\}#s', // get all other media queries
|
555 |
+
) as $regex ): // (((?!\@media).) backreference too memory intensive - rolled back in v 1.4.8.1
|
556 |
+
preg_match_all( $regex, $this->styles, $matches );
|
557 |
+
foreach ( $matches[1] as $segment ):
|
558 |
+
$ruleset[trim( $segment )] = array_shift( $matches[2] ) . ( isset( $ruleset[trim( $segment )] )?$ruleset[trim( $segment )]:'' );
|
559 |
endforeach;
|
560 |
// stripping rulesets leaves base styles
|
561 |
+
$this->styles = preg_replace( $regex, '', $this->styles );
|
562 |
endforeach;
|
563 |
$ruleset[$basequery] = $this->styles;
|
564 |
+
foreach ( $ruleset as $query => $segment ):
|
565 |
// make sure there is semicolon before closing brace
|
566 |
+
$segment = preg_replace( '#(\})#', ";$1", $segment );
|
567 |
+
// parses selectors and corresponding rules
|
568 |
$regex = '#\s([\[\.\#\:\w][\w\-\s\(\)\[\]\'\^\*\.\#\+:,"=>]+?)\s*\{(.*?)\}#s'; //
|
569 |
+
preg_match_all( $regex, $segment, $matches );
|
570 |
+
foreach( $matches[1] as $sel ):
|
571 |
+
$stuff = array_shift( $matches[2] );
|
572 |
+
$this->update_arrays( $template, $query, $sel );
|
573 |
// handle base64 data
|
574 |
$stuff = preg_replace( '#data:([^;]+?);([^\)]+?)\)#s', "data:$1%%semi%%$2)", $stuff );
|
575 |
+
foreach ( explode( ';', $stuff ) as $ruleval ):
|
576 |
+
if ( $this->qskey > CHLD_THM_CFG_MAX_SELECTORS ) break;
|
577 |
+
if ( FALSE === strpos( $ruleval, ':' ) ) continue;
|
578 |
+
list( $rule, $value ) = explode( ':', $ruleval, 2 );
|
579 |
+
$rule = trim( $rule );
|
580 |
+
$rule = preg_replace_callback( "/[^\w\-]/", array( $this, 'to_ascii' ), $rule );
|
581 |
// handle base64 data
|
582 |
+
$value = trim( str_replace( '%%semi%%', ';', $value ) );
|
583 |
|
584 |
$rules = $values = array();
|
585 |
// save important flag
|
586 |
+
$important = $this->is_important( $value );
|
587 |
// normalize color
|
588 |
+
$value = $this->normalize_color( $value );
|
589 |
// normalize font
|
590 |
+
if ( 'font' == $rule ):
|
591 |
+
$this->normalize_font( $value, $rules, $values );
|
592 |
// normalize background
|
593 |
+
elseif( 'background' == $rule ):
|
594 |
+
$this->normalize_background( $value, $rules, $values );
|
595 |
// normalize margin/padding
|
596 |
+
elseif ( 'margin' == $rule || 'padding' == $rule ):
|
597 |
+
$this->normalize_margin_padding( $rule, $value, $rules, $values );
|
598 |
else:
|
599 |
$rules[] = $rule;
|
600 |
$values[] = $value;
|
601 |
endif;
|
602 |
+
foreach ( $rules as $rule ):
|
603 |
+
$value = trim( array_shift( $values ) );
|
604 |
// normalize zero values
|
605 |
+
$value = preg_replace( '#\b0(px|r?em)#', '0', $value );
|
606 |
// normalize gradients
|
607 |
+
if ( FALSE !== strpos( $value, 'gradient' ) ):
|
608 |
+
if ( FALSE !== strpos( $rule, 'filter' ) ):
|
609 |
$rule = 'background-image';
|
610 |
continue; // treat as background-image, we'll add filter rule later
|
611 |
endif;
|
612 |
+
if ( FALSE !== strpos( $value, 'webkit-gradient' ) ) continue; // bail on legacy webkit, we'll add it later
|
613 |
+
$value = $this->encode_gradient( $value );
|
614 |
endif;
|
615 |
// normalize common vendor prefixes
|
616 |
+
$rule = preg_replace( '#(\-(o|ms|moz|webkit)\-)?(' . implode( '|', $this->vendorrule ) . ')#', "$3", $rule );
|
617 |
+
$this->update_arrays( $template, $query, $sel, $rule, $value, $important );
|
618 |
endforeach;
|
619 |
endforeach;
|
620 |
endforeach;
|
628 |
* @media query blocks are sorted using internal heuristics (see sort_queries)
|
629 |
* New selectors are appended to the end of each media query block.
|
630 |
*/
|
631 |
+
function write_css( $backup = FALSE ) {
|
632 |
// write new stylesheet
|
633 |
+
$output = apply_filters( 'chld_thm_cfg_css_header', $this->get_css_header(), $this );
|
634 |
+
$imports = $this->get_prop( 'imports' );
|
635 |
+
if ( !empty( $imports ) ):
|
636 |
+
foreach ( $imports as $import ):
|
637 |
$output .= $import . ';' . LF;
|
638 |
endforeach;
|
639 |
endif;
|
640 |
$output .= LF;
|
641 |
// turn the dictionaries into indexes (value => id into id => value):
|
642 |
+
$rulearr = array_flip( $this->dict_rule );
|
643 |
+
$valarr = array_flip( $this->dict_val );
|
644 |
+
$selarr = array_flip( $this->dict_sel );
|
645 |
+
foreach ( $this->sort_queries() as $query => $sort_order ):
|
646 |
$has_selector = 0;
|
647 |
$sel_output = '';
|
648 |
$selectors = $this->sel_ndx[$this->dict_query[$query]];
|
649 |
+
uasort( $selectors, array( $this, 'cmp_seq' ) );
|
650 |
+
if ( 'base' != $query ) $sel_output .= $query . ' {' . LF;
|
651 |
+
foreach ( $selectors as $selid => $qsid ):
|
652 |
$has_value = 0;
|
653 |
$sel = $selarr[$selid];
|
654 |
+
if ( !empty( $this->val_ndx[$qsid] ) ):
|
655 |
$shorthand = array();
|
656 |
+
foreach ( $this->val_ndx[$qsid] as $ruleid => $valid ):
|
657 |
+
if ( isset( $valid['child'] )
|
658 |
+
&& isset( $valarr[$valid['child']] )
|
659 |
&& '' !== $valarr[$valid['child']]
|
660 |
+
&& ( !isset( $valid['parnt'] ) || $valid['parnt'] != $valid['child'] ) ):
|
661 |
+
if ( ! $has_value ):
|
662 |
+
$sel_output .= isset( $this->dict_seq[$qsid] )?'/*' . $this->dict_seq[$qsid] . '*/' . LF:'';
|
663 |
// show load order
|
664 |
$sel_output .= $sel . ' {' . LF;
|
665 |
$has_value = 1;
|
666 |
$has_selector = 1;
|
667 |
endif;
|
668 |
+
$important_parnt = empty( $valid['i_parnt'] ) ? 0 : 1;
|
669 |
+
$important = isset( $valid['i_child'] ) ? $valid['i_child'] : $important_parnt;
|
670 |
+
$sel_output .= $this->add_vendor_rules( $rulearr[$ruleid], $valarr[$valid['child']], $shorthand, $important );
|
671 |
endif;
|
672 |
endforeach;
|
673 |
+
$sel_output .= $this->encode_shorthand( $shorthand ); // . ( $important ? ' !important' : '' );
|
674 |
+
if ( $has_value ):
|
675 |
$sel_output .= '}' . LF;
|
676 |
endif;
|
677 |
endif;
|
678 |
endforeach;
|
679 |
+
if ( 'base' != $query ) $sel_output .= '}' . LF;
|
680 |
+
if ( $has_selector ) $output .= $sel_output;
|
681 |
endforeach;
|
682 |
+
$stylesheet = apply_filters( 'chld_thm_cfg_target', $this->get_child_target(), $this );
|
683 |
+
if ( $stylesheet_verified = $this->is_file_ok( $stylesheet, 'write' ) ):
|
684 |
global $wp_filesystem; // this was initialized earlier;
|
685 |
// backup current stylesheet
|
686 |
+
if ( $backup && is_file( $stylesheet_verified ) ):
|
687 |
+
$timestamp = date( 'YmdHis', current_time( 'timestamp' ) );
|
688 |
+
$bakfile = preg_replace( "/\.css$/", '', $stylesheet_verified ) . '-' . $timestamp . '.css';
|
689 |
// don't write new stylesheet if backup fails
|
690 |
+
if ( !$wp_filesystem->copy( $this->ctc()->fspath( $stylesheet_verified ), $this->ctc()->fspath( $bakfile ) ) ) return FALSE;
|
691 |
endif;
|
692 |
// write new stylesheet:
|
693 |
// try direct write first, then wp_filesystem write
|
694 |
// stylesheet must already exist and be writable by web server
|
695 |
+
if ( FALSE !== @file_put_contents( $stylesheet_verified, $output ) ): //is_writable( $stylesheet_verified ) &&
|
696 |
return TRUE;
|
697 |
+
elseif ( FALSE !== $wp_filesystem->put_contents( $this->ctc()->fspath( $stylesheet_verified ), $output ) ):
|
698 |
return TRUE;
|
699 |
endif;
|
700 |
endif;
|
707 |
* These are based on commonly used practices and not all vendor prefixed are supported
|
708 |
* TODO: verify this logic against vendor and W3C documentation
|
709 |
*/
|
710 |
+
function add_vendor_rules( $rule, $value, &$shorthand, $important = 0 ) {
|
711 |
$rules = '';
|
712 |
+
if ( 'filter' == $rule && ( FALSE !== strpos( $value, 'progid:DXImageTransform.Microsoft.Gradient' ) ) ) return;
|
713 |
$importantstr = $important ? ' !important' : '';
|
714 |
+
if ( preg_match( "/^(margin|padding)\-(top|right|bottom|left)$/", $rule, $matches ) ):
|
715 |
$shorthand[$matches[1]][$matches[2]] = $value . $importantstr;
|
716 |
return '';
|
717 |
+
elseif ( preg_match( '/^(' . implode( '|', $this->vendorrule ) . ')$/', $rule ) ):
|
718 |
+
foreach( array( 'moz', 'webkit', 'o' ) as $prefix ):
|
719 |
$rules .= ' -' . $prefix . '-' . $rule . ': ' . $value . $importantstr . ';' . LF;
|
720 |
endforeach;
|
721 |
$rules .= ' ' . $rule . ': ' . $value . $importantstr . ';' . LF;
|
722 |
+
elseif ( 'background-image' == $rule ):
|
723 |
// gradient?
|
724 |
|
725 |
+
if ( $gradient = $this->decode_gradient( $value ) ):
|
726 |
// standard gradient
|
727 |
+
foreach( array( 'moz', 'webkit', 'o', 'ms' ) as $prefix ):
|
728 |
$rules .= ' background-image: -' . $prefix . '-' . 'linear-gradient(' . $gradient['origin'] . ', '
|
729 |
. $gradient['color1'] . ', ' . $gradient['color2'] . ')' . $importantstr . ';' . LF;
|
730 |
endforeach;
|
731 |
// W3C standard gradient
|
732 |
// rotate origin 90 degrees
|
733 |
+
if ( preg_match( '/(\d+)deg/', $gradient['origin'], $matches ) ):
|
734 |
+
$org = ( 90 - $matches[1] ) . 'deg';
|
735 |
else:
|
736 |
+
foreach ( preg_split( "/\s+/", $gradient['origin'] ) as $dir ):
|
737 |
+
$dir = strtolower( $dir );
|
738 |
+
$dirs[] = ( 'top' == $dir ? 'bottom' : ( 'bottom' == $dir ? 'top' : ( 'left' == $dir ? 'right' : ( 'right' == $dir ? 'left' : $dir ) ) ) );
|
739 |
endforeach;
|
740 |
+
$org = 'to ' . implode( ' ', $dirs );
|
741 |
endif;
|
742 |
$rules .= ' background-image: linear-gradient(' . $org . ', '
|
743 |
. $gradient['color1'] . ', ' . $gradient['color2'] . ')' . $importantstr . ';' . LF;
|
746 |
// '-webkit-gradient(linear,' .$origin . ', ' . $color1 . ', '. $color2 . ')';
|
747 |
|
748 |
// MS filter gradient
|
749 |
+
$type = ( in_array( $gradient['origin'], array( 'left', 'right', '0deg', '180deg' ) ) ? 1 : 0 );
|
750 |
+
$color1 = preg_replace( "/^#/", '#00', $gradient['color1'] );
|
751 |
$rules .= ' filter: progid:DXImageTransform.Microsoft.Gradient(GradientType=' . $type . ', StartColorStr="'
|
752 |
+
. strtoupper( $color1 ) . '", EndColorStr="' . strtoupper( $gradient['color2'] ) . '")' . $importantstr . ';' . LF;
|
753 |
else:
|
754 |
// url or other value
|
755 |
$rules .= ' ' . $rule . ': ' . $value . $importantstr . ';' . LF;
|
756 |
endif;
|
757 |
else:
|
758 |
+
$rule = preg_replace_callback( "/\d+/", array( $this, 'from_ascii' ), $rule );
|
759 |
$rules .= ' ' . $rule . ': ' . $value . $importantstr . ';' . LF;
|
760 |
endif;
|
761 |
return $rules;
|
766 |
* parses background shorthand value and returns
|
767 |
* normalized rule/value pairs for each property
|
768 |
*/
|
769 |
+
function normalize_background( $value, &$rules, &$values ){
|
770 |
+
if ( FALSE !== strpos( $value, 'gradient' ) ):
|
771 |
// only supporting linear syntax
|
772 |
+
if ( preg_match( '#(linear\-|Microsoft\.)#', $value ) ):
|
773 |
$values[] = $value;
|
774 |
$rules[] = 'background-image';
|
775 |
endif;
|
776 |
else:
|
777 |
$regex = '#(url *\([^\)]+\))#';
|
778 |
+
if ( preg_match( $regex, $value, $matches ) ) $url = $matches[1];
|
779 |
+
$parts = preg_split( $regex, $value );
|
780 |
|
781 |
+
if ( count( $parts ) == 1 ):
|
782 |
// this is a named color or single hex color or none
|
783 |
+
$part = str_replace( ' ', '', $parts[0] );
|
784 |
$rules[] = 'none' == $part ? 'background' : 'background-color';
|
785 |
$values[] = $part;
|
786 |
else:
|
787 |
$rules[] = 'background-image';
|
788 |
$values[] = $url;
|
789 |
+
if ( !empty( $parts[0] ) && '' !== $parts[0] ):
|
790 |
$rules[] = 'background-color';
|
791 |
+
$values[] = trim( $parts[0] );
|
792 |
endif;
|
793 |
$position = array();
|
794 |
+
foreach( preg_split( '/ +/', trim( $parts[1] ) ) as $part ):
|
795 |
+
if ( '' === $part ) continue; // empty( $part ) ||
|
796 |
+
if ( FALSE === strpos( $part, 'repeat' ) ):
|
797 |
$position[] = $part;
|
798 |
else:
|
799 |
$rules[] = 'background-repeat';
|
800 |
$values[] = $part;
|
801 |
endif;
|
802 |
endforeach;
|
803 |
+
if ( count( $position ) ):
|
804 |
$rules[] = 'background-position';
|
805 |
+
$values[] = implode( ' ', $position );
|
806 |
endif;
|
807 |
endif;
|
808 |
endif;
|
813 |
* parses font shorthand value and returns
|
814 |
* normalized rule/value pairs for each property
|
815 |
*/
|
816 |
+
function normalize_font( $value, &$rules, &$values ) {
|
817 |
$regex = '#^((\d+|bold|normal) )?((italic|normal) )?(([\d\.]+(px|r?em|%))[\/ ])?(([\d\.]+(px|r?em|%)?) )?(.+)$#is';
|
818 |
+
preg_match( $regex, $value, $parts );
|
819 |
+
if ( !empty( $parts[2] ) ):
|
820 |
$rules[] = 'font-weight';
|
821 |
$values[] = $parts[2];
|
822 |
endif;
|
823 |
+
if ( !empty( $parts[4] ) ):
|
824 |
$rules[] = 'font-style';
|
825 |
$values[] = $parts[4];
|
826 |
endif;
|
827 |
+
if ( !empty( $parts[6] ) ):
|
828 |
$rules[] = 'font-size';
|
829 |
$values[] = $parts[6];
|
830 |
endif;
|
831 |
+
if ( !empty( $parts[9] ) ):
|
832 |
$rules[] = 'line-height';
|
833 |
$values[] = $parts[9];
|
834 |
endif;
|
835 |
+
if ( !empty( $parts[11] ) ):
|
836 |
$rules[] = 'font-family';
|
837 |
$values[] = $parts[11];
|
838 |
endif;
|
844 |
* normalized rule/value pairs for each property
|
845 |
* TODO: reassemble into shorthand when writing CSS file
|
846 |
*/
|
847 |
+
function normalize_margin_padding( $rule, $value, &$rules, &$values ) {
|
848 |
+
$parts = preg_split( "/ +/", trim( $value ) );
|
849 |
+
if ( !isset( $parts[1] ) ) $parts[1] = $parts[0];
|
850 |
+
if ( !isset( $parts[2] ) ) $parts[2] = $parts[0];
|
851 |
+
if ( !isset( $parts[3] ) ) $parts[3] = $parts[1];
|
852 |
$rules[0] = $rule . '-top';
|
853 |
$values[0] = $parts[0];
|
854 |
$rules[1] = $rule . '-right';
|
859 |
$values[3] = $parts[3];
|
860 |
}
|
861 |
|
862 |
+
/*
|
863 |
+
* encode_shorthand
|
864 |
+
* converts CTC long syntax into CSS shorthand
|
865 |
+
*/
|
866 |
+
function encode_shorthand( $shorthand ) {
|
867 |
$rules = '';
|
868 |
$importantstr = ' !important';
|
869 |
+
foreach ( array_keys( $shorthand ) as $key ):
|
870 |
$important = array();
|
871 |
$rule = array();
|
872 |
$importantct = 0;
|
873 |
// which sides do we have and are they important?
|
874 |
+
foreach( $shorthand[$key] as $side => $val ):
|
875 |
$ict = 0;
|
876 |
+
$rule[$side] = trim( preg_replace( '/'.$importantstr.'/', '', $val, 1, $ict ) );
|
877 |
$important[$side] = $ict;
|
878 |
$importantct += $ict;
|
879 |
endforeach;
|
880 |
// shorthand must have 4 explicit values and all must have same priority
|
881 |
+
if ( 4 == count( $rule ) && ( 0 == $importantct || 4 == $importantct ) ):
|
882 |
// let's try to condense the values into as few as possible, starting with the top value
|
883 |
$parts = array();
|
884 |
$parts[0] = $rule['top'];
|
885 |
// if left is not the same as right, we must use all 4 values
|
886 |
+
if ( $rule['left'] !== $rule['right'] ):
|
887 |
$parts[3] = $rule['left'];
|
888 |
$parts[2] = $rule['bottom'];
|
889 |
$parts[1] = $rule['right'];
|
890 |
endif;
|
891 |
// if top is not the same as bottom, we must use at least 3 values
|
892 |
+
if ( $rule['bottom'] !== $rule['top'] ):
|
893 |
$parts[2] = $rule['bottom'];
|
894 |
$parts[1] = $rule['right'];
|
895 |
endif;
|
896 |
// if top is not the same as right, we must use at least 2 values
|
897 |
+
if ( $rule['right'] !== $rule['top'] ):
|
898 |
$parts[1] = $rule['right'];
|
899 |
endif;
|
900 |
// the order of the sides is critical: top right bottom left
|
901 |
+
ksort( $parts );
|
902 |
+
$shorthandstr = implode( ' ', $parts );
|
903 |
// if important counter is > 0, it must be == 4, add flag
|
904 |
+
$rules .= ' ' . $key . ': ' . $shorthandstr . ( $importantct ? ' ' . $importantstr : '' ) . ';' . LF;
|
905 |
else:
|
906 |
// otherwise return separate rule for each side
|
907 |
+
foreach ( $rule as $side => $value ):
|
908 |
+
$rules .= ' ' . $key . '-' . $side . ': ' . $value . ( $important[$side] ? $importantstr : '' ) . ';' . LF;
|
909 |
endforeach;
|
910 |
endif;
|
911 |
endforeach;
|
918 |
* Currently only supports two-color linear gradients with no inner stops.
|
919 |
* TODO: legacy webkit? more gradients?
|
920 |
*/
|
921 |
+
function encode_gradient( $value ) {
|
922 |
+
// don't try this at home, kids
|
923 |
$regex = '#gradient[^\)]*?\((((top|bottom|left|right)?( (top|bottom|left|right))?|\d+deg),)?([^\)]*[\'"]?(\#\w{3,8}|rgba?\([\d, ]+?\)|hsla?\([\d%, ]+?\))( \d+%)?)([^\)]*[\'"]?(\#\w{3,8}|rgba?\([\d, ]+?\)|hsla?\([\d%, ]+?\))( \d+%)?)([^\)]*gradienttype=[\'"]?(\d)[\'"]?)?[^\)]*\)#i';
|
924 |
$param = $parts = array();
|
925 |
+
preg_match( $regex, $value, $parts );
|
926 |
+
if ( empty( $parts[13] ) ):
|
927 |
+
if ( empty( $parts[2] ) ):
|
928 |
$param[0] = 'top';
|
929 |
else:
|
930 |
+
$param[0] = trim( $parts[2] );
|
931 |
endif;
|
932 |
+
if ( empty( $parts[8] ) ):
|
933 |
$param[2] = '0%';
|
934 |
else:
|
935 |
+
$param[2] = trim( $parts[8] );
|
936 |
endif;
|
937 |
+
if ( empty( $parts[11] ) ):
|
938 |
$param[4] = '100%';
|
939 |
else:
|
940 |
+
$param[4] = trim( $parts[11] );
|
941 |
endif;
|
942 |
+
elseif( '0' == $parts[13] ):
|
943 |
$param[0] = 'top';
|
944 |
$param[2] = '0%';
|
945 |
$param[4] = '100%';
|
946 |
+
elseif ( '1' == $parts[13] ):
|
947 |
$param[0] = 'left';
|
948 |
$param[2] = '0%';
|
949 |
$param[4] = '100%';
|
950 |
endif;
|
951 |
+
if ( isset( $parts[7] ) && isset( $parts[10] ) ):
|
952 |
$param[1] = $parts[7];
|
953 |
$param[3] = $parts[10];
|
954 |
+
ksort( $param );
|
955 |
+
return implode( ':', $param );
|
956 |
else: return $value;
|
957 |
endif;
|
958 |
}
|
959 |
|
960 |
/*
|
961 |
* decode_border
|
962 |
+
* De-normalize CTC border syntax into individual properties.
|
963 |
*/
|
964 |
+
function decode_border( $value ) {
|
965 |
+
if ( preg_match( '#^(0|none)#i', $value ) ):
|
966 |
$parts[0] = $value;
|
967 |
$parts[1] = $parts[2] = '';
|
968 |
else:
|
969 |
+
$parts = preg_split( '#\s+#', $value, 3 );
|
970 |
endif;
|
971 |
return array(
|
972 |
+
'width' => empty( $parts[0] ) ? '' : $parts[0],
|
973 |
+
'style' => empty( $parts[1] ) ? '' : $parts[1],
|
974 |
+
'color' => empty( $parts[2] ) ? '' : $parts[2],
|
975 |
);
|
976 |
}
|
977 |
|
978 |
/*
|
979 |
* decode_gradient
|
980 |
+
* Decode CTC gradient syntax into individual properties.
|
981 |
*/
|
982 |
+
function decode_gradient( $value ) {
|
983 |
+
$parts = explode( ':', $value, 5 );
|
984 |
+
if ( !preg_match( '#(url|none)#i', $value ) && 5 == count( $parts ) ):
|
985 |
return array(
|
986 |
+
'origin' => empty( $parts[0] ) ? '' : $parts[0],
|
987 |
+
'color1' => empty( $parts[1] ) ? '' : $parts[1],
|
988 |
+
'stop1' => empty( $parts[2] ) ? '' : $parts[2],
|
989 |
+
'color2' => empty( $parts[3] ) ? '' : $parts[3],
|
990 |
+
'stop2' => empty( $parts[4] ) ? '' : $parts[4],
|
991 |
);
|
992 |
endif;
|
993 |
return FALSE;
|
997 |
* denorm_rule_val
|
998 |
* Return array of unique values corresponding to specific rule
|
999 |
*/
|
1000 |
+
function denorm_rule_val( $ruleid ) {
|
1001 |
$rule_sel_arr = array();
|
1002 |
+
$val_arr = array_flip( $this->dict_val );
|
1003 |
+
foreach ( $this->val_ndx as $selid => $rules ):
|
1004 |
+
if ( !isset( $rules[$ruleid] ) ) continue;
|
1005 |
+
foreach ( $rules[$ruleid] as $theme => $val ):
|
1006 |
+
if ( !isset( $val_arr[$val] ) || '' === $val_arr[$val] ) continue;
|
1007 |
$rule_sel_arr[$val] = $val_arr[$val];
|
1008 |
endforeach;
|
1009 |
endforeach;
|
1015 |
* Return array of queries, selectors, rules, and values corresponding to
|
1016 |
* specific rule/value combo grouped by query, selector
|
1017 |
*/
|
1018 |
+
function denorm_val_query( $valid, $rule ) {
|
1019 |
$value_query_arr = array();
|
1020 |
+
foreach ( $this->val_ndx as $qsid => $rules ):
|
1021 |
+
foreach ( $rules as $ruleid => $values ):
|
1022 |
+
if ( $ruleid != $this->dict_rule[$rule] ) continue;
|
1023 |
+
foreach ( $values as $name => $val ):
|
1024 |
+
if ( 'i' == $name || $val != $valid ) continue;
|
1025 |
+
$selarr = $this->denorm_query_sel( $qsid );
|
1026 |
+
$valarr = $this->denorm_sel_val( $qsid );
|
1027 |
$value_query_arr[$rule][$selarr['query']][$qsid] = $valarr;
|
1028 |
endforeach;
|
1029 |
endforeach;
|
1035 |
* denorm_query_sel
|
1036 |
* Return id, query and selector values of a specific qsid (query-selector ID)
|
1037 |
*/
|
1038 |
+
function denorm_query_sel( $qsid ) {
|
1039 |
+
$queryarr = array_flip( $this->dict_query );
|
1040 |
+
$selarr = array_flip( $this->dict_sel );
|
1041 |
+
$this->dict_seq[$qsid] = isset( $this->dict_seq[$qsid] ) ? $this->dict_seq[$qsid] : $qsid;
|
1042 |
return array(
|
1043 |
'id' => $qsid,
|
1044 |
'query' => $queryarr[$this->dict_qs[$qsid]['q']],
|
1052 |
* Return array of rules, and values matching specific qsid (query-selector ID)
|
1053 |
* grouped by query, selector
|
1054 |
*/
|
1055 |
+
function denorm_sel_val( $qsid ) {
|
1056 |
+
$selarr = $this->denorm_query_sel( $qsid );
|
1057 |
+
$valarr = array_flip( $this->dict_val );
|
1058 |
+
$rulearr = array_flip( $this->dict_rule );
|
1059 |
+
if ( isset( $this->val_ndx[$qsid] ) && is_array( $this->val_ndx[$qsid] ) ):
|
1060 |
+
foreach ( $this->val_ndx[$qsid] as $ruleid => $values ):
|
1061 |
+
foreach ( $values as $name => $val ):
|
1062 |
+
if ( 'i_parnt' == $name || 'i_child' == $name ):
|
1063 |
+
$selarr['value'][$rulearr[$ruleid]][$name] = ( empty( $val ) ? 0 : 1 );
|
1064 |
+
elseif ( !isset( $valarr[$val] ) || '' === $valarr[$val] ):
|
1065 |
continue;
|
1066 |
else:
|
1067 |
$selarr['value'][$rulearr[$ruleid]][$name] = $valarr[$val];
|
1077 |
* denorm_sel_ndx
|
1078 |
* Return denormalized array containing query and selector heirarchy
|
1079 |
*/
|
1080 |
+
function denorm_sel_ndx( $query = NULL ) {
|
1081 |
$sel_ndx_norm = array();
|
1082 |
+
$queryarr = array_flip( $this->dict_query );
|
1083 |
+
$selarr = array_flip( $this->dict_sel );
|
1084 |
+
foreach( $this->sel_ndx as $queryid => $sel ):
|
1085 |
+
foreach( $sel as $selid => $qsid ):
|
1086 |
$sel_ndx_norm[$queryarr[$queryid]][$selarr[$selid]] = $qsid;
|
1087 |
endforeach;
|
1088 |
endforeach;
|
1089 |
+
return empty( $query ) ? $sel_ndx_norm : $sel_ndx_norm[$query];
|
1090 |
}
|
1091 |
|
1092 |
/*
|
1094 |
* Strip important flag from value ref and return boolean
|
1095 |
* Value is updated because it is a ref
|
1096 |
*/
|
1097 |
+
function is_important( &$value ) {
|
1098 |
$important = 0;
|
1099 |
+
$value = trim( str_ireplace( '!important', '', $value, $important ) );
|
1100 |
return $important;
|
1101 |
}
|
1102 |
|
1110 |
*/
|
1111 |
function sort_queries() {
|
1112 |
$queries = array();
|
1113 |
+
$queryarr = array_flip( $this->dict_query );
|
1114 |
+
foreach ( array_keys( $this->sel_ndx ) as $queryid ):
|
1115 |
$query = $queryarr[$queryid];
|
1116 |
+
if ( 'base' == $query ):
|
1117 |
$queries['base'] = -999999;
|
1118 |
continue;
|
1119 |
endif;
|
1120 |
+
if ( preg_match( "/((min|max)(\-device)?\-width)\s*:\s*(\d+)/", $query, $matches ) ):
|
1121 |
$queries[$query] = 'min-width' == $matches[1] ? $matches[4] : -$matches[4];
|
1122 |
else:
|
1123 |
$queries[$query] = $queryid - 10000;
|
1124 |
endif;
|
1125 |
endforeach;
|
1126 |
+
asort( $queries );
|
1127 |
return $queries;
|
1128 |
}
|
1129 |
|
1130 |
// sort selectors based on dict_seq if exists, otherwise qsid
|
1131 |
+
function cmp_seq( $a, $b ) {
|
1132 |
+
$cmpa = isset( $this->dict_seq[$a] ) ? $this->dict_seq[$a] : $a;
|
1133 |
+
$cmpb = isset( $this->dict_seq[$b] ) ? $this->dict_seq[$b] : $b;
|
1134 |
+
if ( $cmpa == $cmpb ) return 0;
|
1135 |
+
return ( $cmpa < $cmpb ) ? -1 : 1;
|
1136 |
}
|
1137 |
|
1138 |
/*
|
1141 |
* flattens to array
|
1142 |
* and stringifies NULLs
|
1143 |
*/
|
1144 |
+
function obj_to_utf8( $data ) {
|
1145 |
|
1146 |
+
if ( is_object( $data ) ) {
|
1147 |
+
$data = get_object_vars( $data );
|
1148 |
}
|
1149 |
+
if ( is_array( $data ) ) {
|
1150 |
+
return array_map( array( &$this, __FUNCTION__ ), $data );
|
1151 |
}
|
1152 |
else {
|
1153 |
+
return is_null( $data ) ? '' : utf8_encode( $data );
|
1154 |
}
|
1155 |
}
|
1156 |
+
// convert ascii character into decimal value
|
1157 |
+
function to_ascii( $matches ) {
|
1158 |
+
return ord( $matches[0] );
|
1159 |
}
|
1160 |
+
// convert decimal value into ascii character
|
1161 |
+
function from_ascii( $matches ) {
|
1162 |
+
return chr( $matches[0] );
|
1163 |
}
|
1164 |
|
1165 |
/* is_file_ok
|
1166 |
* verify file exists and is in valid location
|
1167 |
*/
|
1168 |
+
function is_file_ok( $stylesheet, $permission = 'read' ) {
|
1169 |
// remove any ../ manipulations
|
1170 |
+
$stylesheet = preg_replace( "%\.\./%", '/', $stylesheet );
|
1171 |
+
if ( 'read' == $permission && !is_file( $stylesheet ) ) return FALSE;
|
1172 |
+
if ( 'search' == $permission && !is_dir( $stylesheet ) ) return FALSE;
|
1173 |
// sanity check for php files
|
1174 |
+
//if ( !preg_match( '%' . preg_quote( $ext ) . '$%', $stylesheet ) ) return FALSE;
|
1175 |
// check if in themes dir;
|
1176 |
+
if ( preg_match( '%^' . preg_quote( get_theme_root() ) . '%', $stylesheet ) ) return $stylesheet;
|
1177 |
// check if in plugins dir
|
1178 |
+
if ( preg_match( '%^' . preg_quote( WP_PLUGIN_DIR ) . '%', $stylesheet ) ) return $stylesheet;
|
1179 |
return FALSE;
|
1180 |
}
|
1181 |
+
/* normalize_color
|
1182 |
+
* Sets hex string to lowercase and shortens to 3 char format if possible
|
1183 |
+
*/
|
1184 |
+
function normalize_color( $value ) {
|
1185 |
+
$value = preg_replace_callback( "/#([0-9A-F]{3}([0-9A-F]{3})?)/i", array( $this, 'tolower' ), $value );
|
1186 |
$value = preg_replace( "/#([0-9A-F])\\1([0-9A-F])\\2([0-9A-F])\\3/i", "#$1$2$3", $value );
|
1187 |
return $value;
|
1188 |
}
|
1189 |
+
// callback for normalize_color regex
|
1190 |
+
function tolower( $matches ) {
|
1191 |
+
return '#' . strtolower( $matches[1] );
|
1192 |
}
|
1193 |
}
|
1194 |
?>
|
includes/class-ctc-ui.php
CHANGED
@@ -1,20 +1,20 @@
|
|
1 |
<?php
|
2 |
// Exit if accessed directly
|
3 |
-
if ( !defined('ABSPATH')) exit;
|
4 |
/*
|
5 |
Class: Child_Theme_Configurator_UI
|
6 |
Plugin URI: http://www.lilaeamedia.com/plugins/child-theme-configurator/
|
7 |
Description: Handles the plugin User Interface
|
8 |
-
Version: 1.6.
|
9 |
Author: Lilaea Media
|
10 |
Author URI: http://www.lilaeamedia.com/
|
11 |
Text Domain: chld_thm_cfg
|
12 |
Domain Path: /lang
|
13 |
License: GPLv2
|
14 |
-
Copyright (C) 2014 Lilaea Media
|
15 |
*/
|
16 |
class ChildThemeConfiguratorUI {
|
17 |
-
|
18 |
function ctc() {
|
19 |
global $chld_thm_cfg;
|
20 |
return $chld_thm_cfg;
|
@@ -23,71 +23,71 @@ class ChildThemeConfiguratorUI {
|
|
23 |
function render() {
|
24 |
$css = $this->ctc()->css;
|
25 |
$themes = $this->ctc()->themes;
|
26 |
-
$parent = isset($_GET['ctc_parent']) ? sanitize_text_field($_GET['ctc_parent']) : $css->get_prop('parnt');
|
27 |
-
$child = $css->get_prop('child');
|
28 |
-
$configtype = $css->get_prop('configtype');
|
29 |
-
if (empty($configtype)) $configtype = 'theme';
|
30 |
-
$hidechild = (count($themes['child']) ? '' : 'style="display:none"');
|
31 |
-
$enqueueset = 'theme' != $configtype || isset($css->enqueue);
|
32 |
-
$mustimport = $this->parent_stylesheet_check($parent);
|
33 |
-
$imports = $css->get_prop('imports');
|
34 |
$id = 0;
|
35 |
$this->ctc()->fs_method = get_filesystem_method();
|
36 |
add_thickbox();
|
37 |
-
add_action('chld_thm_cfg_related_links', array($this, 'lilaea_plug'));
|
38 |
-
include ($this->ctc()->pluginPath .'/includes/forms/main.php');
|
39 |
}
|
40 |
|
41 |
-
function parent_stylesheet_check($parent) {
|
42 |
-
$file = trailingslashit(get_theme_root()) . trailingslashit($parent) . 'header.php';
|
43 |
$regex = '/<link[^>]+?stylesheet_ur[li]/is';
|
44 |
-
if (file_exists($file)):
|
45 |
-
$contents = file_get_contents($file);
|
46 |
-
if (preg_match($regex, $contents)) return TRUE;
|
47 |
endif;
|
48 |
return FALSE;
|
49 |
}
|
50 |
|
51 |
|
52 |
-
function render_theme_menu($template = 'child', $selected = NULL) {
|
53 |
?>
|
54 |
<select class="ctc-select" id="ctc_theme_<?php echo $template; ?>" name="ctc_theme_<?php echo $template; ?>" style="visibility:hidden"><?php
|
55 |
-
foreach ($this->ctc()->themes[$template] as $slug => $theme)
|
56 |
-
echo '<option value="' . $slug . '"' . ($slug == $selected ? ' selected' : '') . '>'
|
57 |
-
. esc_attr($theme['Name']) . '</option>' . LF; ?>
|
58 |
</select>
|
59 |
<div style="display:none">
|
60 |
<?php
|
61 |
-
foreach ($this->ctc()->themes[$template] as $slug => $theme)
|
62 |
-
include ($this->ctc()->pluginPath . 'includes/forms/themepreview.php'); ?>
|
63 |
</div>
|
64 |
<?php
|
65 |
}
|
66 |
|
67 |
-
function render_file_form($template = 'parnt') {
|
68 |
global $wp_filesystem;
|
69 |
-
if ($theme = $this->ctc()->css->get_prop($template)):
|
70 |
-
$themeroot = trailingslashit(get_theme_root()) . trailingslashit($theme);
|
71 |
-
$files = $this->ctc()->get_files($theme);
|
72 |
$counter = 0;
|
73 |
-
sort($files);
|
74 |
ob_start();
|
75 |
-
foreach ($files as $file):
|
76 |
-
$templatefile = preg_replace('%\.php$%', '', $file);
|
77 |
-
$excludes = implode("|", (array) apply_filters('chld_thm_cfg_template_excludes', $this->ctc()->excludes));
|
78 |
-
if ('parnt' == $template && (preg_match('%^(' . $excludes . ')\w*\/%',$templatefile)
|
79 |
-
|| 'functions' == basename($templatefile))) continue;
|
80 |
include ( $this->ctc()->pluginPath . 'includes/forms/file.php' );
|
81 |
endforeach;
|
82 |
-
if ('child' == $template && ($backups = $this->ctc()->get_files($theme, 'backup'))):
|
83 |
-
foreach ( $backups as $backup => $label):
|
84 |
-
$templatefile = preg_replace('%\.css$%', '', $backup);
|
85 |
include ( $this->ctc()->pluginPath . 'includes/forms/backup.php' );
|
86 |
endforeach;
|
87 |
endif;
|
88 |
$inputs = ob_get_contents();
|
89 |
ob_end_clean();
|
90 |
-
if ($counter):
|
91 |
include ( $this->ctc()->pluginPath . 'includes/forms/fileform.php' );
|
92 |
endif;
|
93 |
endif;
|
@@ -95,29 +95,29 @@ class ChildThemeConfiguratorUI {
|
|
95 |
|
96 |
function render_image_form() {
|
97 |
|
98 |
-
if ($theme = $this->ctc()->css->get_prop('child')):
|
99 |
-
$themeuri = trailingslashit(get_theme_root_uri()) . trailingslashit($theme);
|
100 |
-
$files = $this->ctc()->get_files($theme, 'img');
|
101 |
|
102 |
$counter = 0;
|
103 |
-
sort($files);
|
104 |
ob_start();
|
105 |
-
foreach ($files as $file):
|
106 |
-
$templatefile = preg_replace('/^images\//', '', $file);
|
107 |
include( $this->ctc()->pluginPath . 'includes/forms/image.php' );
|
108 |
endforeach;
|
109 |
$inputs = ob_get_contents();
|
110 |
ob_end_clean();
|
111 |
-
if ($counter) include( $this->ctc()->pluginPath . 'includes/forms/images.php' );
|
112 |
endif;
|
113 |
}
|
114 |
|
115 |
function get_theme_screenshot() {
|
116 |
|
117 |
-
foreach (array_keys($this->ctc()->imgmimes) as $extreg):
|
118 |
-
foreach (explode('|', $extreg) as $ext):
|
119 |
-
if ($screenshot = $this->ctc()->css->is_file_ok($this->ctc()->css->get_child_target('screenshot.' . $ext))):
|
120 |
-
$screenshot = trailingslashit(get_theme_root_uri()) . $this->ctc()->theme_basename('', $screenshot);
|
121 |
return $screenshot . '?' . time();
|
122 |
endif;
|
123 |
endforeach;
|
@@ -127,52 +127,60 @@ class ChildThemeConfiguratorUI {
|
|
127 |
|
128 |
function settings_errors() {
|
129 |
|
130 |
-
if (count($this->ctc()->errors)):
|
131 |
echo '<div class="error"><ul>' . LF;
|
132 |
-
foreach ($this->ctc()->errors as $err):
|
133 |
echo '<li>' . $err . '</li>' . LF;
|
134 |
endforeach;
|
135 |
echo '</ul></div>' . LF;
|
136 |
-
elseif (isset($_GET['updated'])):
|
137 |
echo '<div class="updated">' . LF;
|
138 |
-
if ( 8 == $_GET['updated']):
|
139 |
-
echo '<p>' . __('Child Theme files modified successfully.', 'chld_thm_cfg') . '</p>' . LF;
|
140 |
else:
|
141 |
-
|
142 |
-
'
|
143 |
-
|
144 |
-
|
145 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
146 |
echo '</div>' . LF;
|
147 |
endif;
|
148 |
}
|
149 |
|
150 |
function render_help_content() {
|
151 |
global $wp_version;
|
152 |
-
if ( version_compare( $wp_version, '3.3') >= 0 ) {
|
153 |
|
154 |
$screen = get_current_screen();
|
155 |
|
156 |
// load help content via output buffer so we can use plain html for updates
|
157 |
// then use regex to parse for help tab parameter values
|
158 |
|
159 |
-
$regex_sidebar = '/' . preg_quote('<!-- BEGIN sidebar -->') . '(.*?)' . preg_quote('<!-- END sidebar -->') . '/s';
|
160 |
-
$regex_tab = '/' . preg_quote('<!-- BEGIN tab -->') . '\s*<h\d id="(.*?)">(.*?)<\/h\d>(.*?)' . preg_quote('<!-- END tab -->') . '/s';
|
161 |
ob_start();
|
162 |
// stub for multiple languages future release
|
163 |
-
include($this->ctc()->pluginPath . 'includes/help/help_en_US.php');
|
164 |
$help_raw = ob_get_contents();
|
165 |
ob_end_clean();
|
166 |
// parse raw html for tokens
|
167 |
-
preg_match($regex_sidebar, $help_raw, $sidebar);
|
168 |
-
preg_match_all($regex_tab, $help_raw, $tabs);
|
169 |
|
170 |
// Add help tabs
|
171 |
-
if (isset($tabs[1])):
|
172 |
-
while(count($tabs[1])):
|
173 |
-
$id = array_shift($tabs[1]);
|
174 |
-
$title = array_shift($tabs[2]);
|
175 |
-
$content = array_shift($tabs[3]);
|
176 |
$screen->add_help_tab( array(
|
177 |
'id' => $id,
|
178 |
'title' => $title,
|
@@ -180,13 +188,13 @@ class ChildThemeConfiguratorUI {
|
|
180 |
) );
|
181 |
endwhile;
|
182 |
endif;
|
183 |
-
if (isset($sidebar[1]))
|
184 |
-
$screen->set_help_sidebar($sidebar[1]);
|
185 |
|
186 |
}
|
187 |
}
|
188 |
function lilaea_plug() {
|
189 |
-
include ($this->ctc()->pluginPath . 'includes/forms/related.php');
|
190 |
}
|
191 |
}
|
192 |
?>
|
1 |
<?php
|
2 |
// Exit if accessed directly
|
3 |
+
if ( !defined( 'ABSPATH' ) ) exit;
|
4 |
/*
|
5 |
Class: Child_Theme_Configurator_UI
|
6 |
Plugin URI: http://www.lilaeamedia.com/plugins/child-theme-configurator/
|
7 |
Description: Handles the plugin User Interface
|
8 |
+
Version: 1.6.3
|
9 |
Author: Lilaea Media
|
10 |
Author URI: http://www.lilaeamedia.com/
|
11 |
Text Domain: chld_thm_cfg
|
12 |
Domain Path: /lang
|
13 |
License: GPLv2
|
14 |
+
Copyright (C) 2014-2015 Lilaea Media
|
15 |
*/
|
16 |
class ChildThemeConfiguratorUI {
|
17 |
+
// helper function to globalize ctc object
|
18 |
function ctc() {
|
19 |
global $chld_thm_cfg;
|
20 |
return $chld_thm_cfg;
|
23 |
function render() {
|
24 |
$css = $this->ctc()->css;
|
25 |
$themes = $this->ctc()->themes;
|
26 |
+
$parent = isset( $_GET['ctc_parent'] ) ? sanitize_text_field( $_GET['ctc_parent'] ) : $css->get_prop( 'parnt' );
|
27 |
+
$child = $css->get_prop( 'child' );
|
28 |
+
$configtype = $css->get_prop( 'configtype' );
|
29 |
+
if ( empty( $configtype ) ) $configtype = 'theme';
|
30 |
+
$hidechild = ( count( $themes['child'] ) ? '' : 'style="display:none"' );
|
31 |
+
$enqueueset = 'theme' != $configtype || isset( $css->enqueue );
|
32 |
+
$mustimport = $this->parent_stylesheet_check( $parent );
|
33 |
+
$imports = $css->get_prop( 'imports' );
|
34 |
$id = 0;
|
35 |
$this->ctc()->fs_method = get_filesystem_method();
|
36 |
add_thickbox();
|
37 |
+
add_action( 'chld_thm_cfg_related_links', array( $this, 'lilaea_plug' ) );
|
38 |
+
include ( $this->ctc()->pluginPath .'/includes/forms/main.php' );
|
39 |
}
|
40 |
|
41 |
+
function parent_stylesheet_check( $parent ) {
|
42 |
+
$file = trailingslashit( get_theme_root() ) . trailingslashit( $parent ) . 'header.php';
|
43 |
$regex = '/<link[^>]+?stylesheet_ur[li]/is';
|
44 |
+
if ( file_exists( $file ) ):
|
45 |
+
$contents = file_get_contents( $file );
|
46 |
+
if ( preg_match( $regex, $contents ) ) return TRUE;
|
47 |
endif;
|
48 |
return FALSE;
|
49 |
}
|
50 |
|
51 |
|
52 |
+
function render_theme_menu( $template = 'child', $selected = NULL ) {
|
53 |
?>
|
54 |
<select class="ctc-select" id="ctc_theme_<?php echo $template; ?>" name="ctc_theme_<?php echo $template; ?>" style="visibility:hidden"><?php
|
55 |
+
foreach ( $this->ctc()->themes[$template] as $slug => $theme )
|
56 |
+
echo '<option value="' . $slug . '"' . ( $slug == $selected ? ' selected' : '' ) . '>'
|
57 |
+
. esc_attr( $theme['Name'] ) . '</option>' . LF; ?>
|
58 |
</select>
|
59 |
<div style="display:none">
|
60 |
<?php
|
61 |
+
foreach ( $this->ctc()->themes[$template] as $slug => $theme )
|
62 |
+
include ( $this->ctc()->pluginPath . 'includes/forms/themepreview.php' ); ?>
|
63 |
</div>
|
64 |
<?php
|
65 |
}
|
66 |
|
67 |
+
function render_file_form( $template = 'parnt' ) {
|
68 |
global $wp_filesystem;
|
69 |
+
if ( $theme = $this->ctc()->css->get_prop( $template ) ):
|
70 |
+
$themeroot = trailingslashit( get_theme_root() ) . trailingslashit( $theme );
|
71 |
+
$files = $this->ctc()->get_files( $theme );
|
72 |
$counter = 0;
|
73 |
+
sort( $files );
|
74 |
ob_start();
|
75 |
+
foreach ( $files as $file ):
|
76 |
+
$templatefile = preg_replace( '%\.php$%', '', $file );
|
77 |
+
$excludes = implode( "|", ( array ) apply_filters( 'chld_thm_cfg_template_excludes', $this->ctc()->excludes ) );
|
78 |
+
if ( 'parnt' == $template && ( preg_match( '%^(' . $excludes . ' )\w*\/%',$templatefile )
|
79 |
+
|| 'functions' == basename( $templatefile ) ) ) continue;
|
80 |
include ( $this->ctc()->pluginPath . 'includes/forms/file.php' );
|
81 |
endforeach;
|
82 |
+
if ( 'child' == $template && ( $backups = $this->ctc()->get_files( $theme, 'backup' ) ) ):
|
83 |
+
foreach ( $backups as $backup => $label ):
|
84 |
+
$templatefile = preg_replace( '%\.css$%', '', $backup );
|
85 |
include ( $this->ctc()->pluginPath . 'includes/forms/backup.php' );
|
86 |
endforeach;
|
87 |
endif;
|
88 |
$inputs = ob_get_contents();
|
89 |
ob_end_clean();
|
90 |
+
if ( $counter ):
|
91 |
include ( $this->ctc()->pluginPath . 'includes/forms/fileform.php' );
|
92 |
endif;
|
93 |
endif;
|
95 |
|
96 |
function render_image_form() {
|
97 |
|
98 |
+
if ( $theme = $this->ctc()->css->get_prop( 'child' ) ):
|
99 |
+
$themeuri = trailingslashit( get_theme_root_uri() ) . trailingslashit( $theme );
|
100 |
+
$files = $this->ctc()->get_files( $theme, 'img' );
|
101 |
|
102 |
$counter = 0;
|
103 |
+
sort( $files );
|
104 |
ob_start();
|
105 |
+
foreach ( $files as $file ):
|
106 |
+
$templatefile = preg_replace( '/^images\//', '', $file );
|
107 |
include( $this->ctc()->pluginPath . 'includes/forms/image.php' );
|
108 |
endforeach;
|
109 |
$inputs = ob_get_contents();
|
110 |
ob_end_clean();
|
111 |
+
if ( $counter ) include( $this->ctc()->pluginPath . 'includes/forms/images.php' );
|
112 |
endif;
|
113 |
}
|
114 |
|
115 |
function get_theme_screenshot() {
|
116 |
|
117 |
+
foreach ( array_keys( $this->ctc()->imgmimes ) as $extreg ):
|
118 |
+
foreach ( explode( '|', $extreg ) as $ext ):
|
119 |
+
if ( $screenshot = $this->ctc()->css->is_file_ok( $this->ctc()->css->get_child_target( 'screenshot.' . $ext ) ) ):
|
120 |
+
$screenshot = trailingslashit( get_theme_root_uri() ) . $this->ctc()->theme_basename( '', $screenshot );
|
121 |
return $screenshot . '?' . time();
|
122 |
endif;
|
123 |
endforeach;
|
127 |
|
128 |
function settings_errors() {
|
129 |
|
130 |
+
if ( count( $this->ctc()->errors ) ):
|
131 |
echo '<div class="error"><ul>' . LF;
|
132 |
+
foreach ( $this->ctc()->errors as $err ):
|
133 |
echo '<li>' . $err . '</li>' . LF;
|
134 |
endforeach;
|
135 |
echo '</ul></div>' . LF;
|
136 |
+
elseif ( isset( $_GET['updated'] ) ):
|
137 |
echo '<div class="updated">' . LF;
|
138 |
+
if ( 8 == $_GET['updated'] ):
|
139 |
+
echo '<p>' . __( 'Child Theme files modified successfully.', 'chld_thm_cfg' ) . '</p>' . LF;
|
140 |
else:
|
141 |
+
$child_theme = wp_get_theme( $this->ctc()->css->get_prop( 'child' ) );
|
142 |
+
echo '<p>' . apply_filters( 'chld_thm_cfg_update_msg', sprintf( __( 'Child Theme <strong>%s</strong> has been generated successfully.
|
143 |
+
', 'chld_thm_cfg' ), $child_theme->Name ), $this->ctc() ) . LF;
|
144 |
+
if ( ! $this->ctc()->css->get_prop( 'configtype' ) || $this->ctc()->css->get_prop( 'configtype' ) == 'theme' ):
|
145 |
+
echo '<strong>' . __( 'IMPORTANT:', 'chld_thm_cfg' ) . LF;
|
146 |
+
if ( is_multisite() && !$child_theme->is_allowed() ):
|
147 |
+
echo 'You must <a href="' . network_admin_url( '/themes.php' ) . '" title="' . __( 'Go to Themes', 'chld_thm_cfg' ) . '" class="ctc-live-preview">' . __( 'Network enable', 'chld_thm_cfg' ) . '</a> ' . __( 'your child theme.', 'chld_thm_cfg' );
|
148 |
+
else:
|
149 |
+
echo '<a href="' . admin_url( '/customize.php?theme=' . $this->ctc()->css->get_prop( 'child' ) ) . '" title="' . __( 'Live Preview', 'chld_thm_cfg' ) . '" class="ctc-live-preview">' . __( 'Test your child theme', 'chld_thm_cfg' ) . '</a> ' . __( 'before activating.', 'chld_thm_cfg' );
|
150 |
+
endif;
|
151 |
+
echo '</strong></p>' . LF;
|
152 |
+
endif;
|
153 |
+
endif;
|
154 |
echo '</div>' . LF;
|
155 |
endif;
|
156 |
}
|
157 |
|
158 |
function render_help_content() {
|
159 |
global $wp_version;
|
160 |
+
if ( version_compare( $wp_version, '3.3' ) >= 0 ) {
|
161 |
|
162 |
$screen = get_current_screen();
|
163 |
|
164 |
// load help content via output buffer so we can use plain html for updates
|
165 |
// then use regex to parse for help tab parameter values
|
166 |
|
167 |
+
$regex_sidebar = '/' . preg_quote( '<!-- BEGIN sidebar -->' ) . '(.*?)' . preg_quote( '<!-- END sidebar -->' ) . '/s';
|
168 |
+
$regex_tab = '/' . preg_quote( '<!-- BEGIN tab -->' ) . '\s*<h\d id="(.*?)">(.*?)<\/h\d>(.*?)' . preg_quote( '<!-- END tab -->' ) . '/s';
|
169 |
ob_start();
|
170 |
// stub for multiple languages future release
|
171 |
+
include( $this->ctc()->pluginPath . 'includes/help/help_en_US.php' );
|
172 |
$help_raw = ob_get_contents();
|
173 |
ob_end_clean();
|
174 |
// parse raw html for tokens
|
175 |
+
preg_match( $regex_sidebar, $help_raw, $sidebar );
|
176 |
+
preg_match_all( $regex_tab, $help_raw, $tabs );
|
177 |
|
178 |
// Add help tabs
|
179 |
+
if ( isset( $tabs[1] ) ):
|
180 |
+
while( count( $tabs[1] ) ):
|
181 |
+
$id = array_shift( $tabs[1] );
|
182 |
+
$title = array_shift( $tabs[2] );
|
183 |
+
$content = array_shift( $tabs[3] );
|
184 |
$screen->add_help_tab( array(
|
185 |
'id' => $id,
|
186 |
'title' => $title,
|
188 |
) );
|
189 |
endwhile;
|
190 |
endif;
|
191 |
+
if ( isset( $sidebar[1] ) )
|
192 |
+
$screen->set_help_sidebar( $sidebar[1] );
|
193 |
|
194 |
}
|
195 |
}
|
196 |
function lilaea_plug() {
|
197 |
+
include ( $this->ctc()->pluginPath . 'includes/forms/related.php' );
|
198 |
}
|
199 |
}
|
200 |
?>
|
includes/class-ctc.php
CHANGED
@@ -1,18 +1,18 @@
|
|
1 |
<?php
|
2 |
// Exit if accessed directly
|
3 |
-
if ( !defined('ABSPATH')) exit;
|
4 |
|
5 |
/*
|
6 |
Class: Child_Theme_Configurator
|
7 |
Plugin URI: http://www.lilaeamedia.com/plugins/child-theme-configurator/
|
8 |
Description: Main Controller Class
|
9 |
-
Version: 1.6.
|
10 |
Author: Lilaea Media
|
11 |
Author URI: http://www.lilaeamedia.com/
|
12 |
Text Domain: chld_thm_cfg
|
13 |
Domain Path: /lang
|
14 |
License: GPLv2
|
15 |
-
Copyright (C) 2014 Lilaea Media
|
16 |
*/
|
17 |
class ChildThemeConfiguratorAdmin {
|
18 |
|
@@ -79,72 +79,72 @@ class ChildThemeConfiguratorAdmin {
|
|
79 |
var $cache_updates = TRUE;
|
80 |
var $swatch_text = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.';
|
81 |
|
82 |
-
function __construct($file) {
|
83 |
$this->pluginPath = trailingslashit( dirname( $file ) );
|
84 |
-
$this->pluginURL = plugin_dir_url($file);
|
85 |
$this->menuName = CHLD_THM_CFG_MENU; // backward compatability for plugins extension
|
86 |
}
|
87 |
function render() {
|
88 |
$this->ui->render();
|
89 |
}
|
90 |
function enqueue_scripts() {
|
91 |
-
wp_enqueue_style('chld-thm-cfg-admin', $this->pluginURL . 'css/chld-thm-cfg.css', array(), '1.6.
|
92 |
|
93 |
// we need to use local jQuery UI Widget/Menu/Selectmenu 1.11.2 because selectmenu is not included in < 1.11.2
|
94 |
// this will be updated in a later release to use WP Core scripts when it is widely adopted
|
95 |
-
if (!wp_script_is('jquery-ui-selectmenu', 'registered')): // selectmenu.min.js
|
96 |
-
wp_enqueue_script('jquery-ui-selectmenu', $this->pluginURL . 'js/selectmenu.min.js', array('jquery','jquery-ui-core','jquery-ui-position'), FALSE, TRUE);
|
97 |
endif;
|
98 |
-
wp_enqueue_script('ctc-thm-cfg-ctcgrad', $this->pluginURL . 'js/ctcgrad.min.js', array('jquery'), FALSE, TRUE);
|
99 |
-
wp_enqueue_script('chld-thm-cfg-admin', $this->pluginURL . 'js/chld-thm-cfg.min.js',
|
100 |
array(
|
101 |
'jquery-ui-autocomplete',
|
102 |
'jquery-ui-selectmenu',
|
103 |
'wp-color-picker',
|
104 |
), FALSE, TRUE );
|
105 |
-
$localize_array = apply_filters('chld_thm_cfg_localize_script', array(
|
106 |
'ssl' => is_ssl(),
|
107 |
'homeurl' => get_home_url(),
|
108 |
'ajaxurl' => admin_url( 'admin-ajax.php' ),
|
109 |
'theme_uri' => get_theme_root_uri(),
|
110 |
'page' => CHLD_THM_CFG_MENU,
|
111 |
'themes' => $this->themes,
|
112 |
-
'source' => apply_filters('chld_thm_cfg_source_uri', get_theme_root_uri() . '/'
|
113 |
-
. $this->css->get_prop('parnt') . '/style.css', $this->css),
|
114 |
-
'target' => apply_filters('chld_thm_cfg_target_uri', get_theme_root_uri() . '/'
|
115 |
-
. $this->css->get_prop('child') . '/style.css', $this->css),
|
116 |
-
'parnt' => $this->css->get_prop('parnt'),
|
117 |
-
'child' => $this->css->get_prop('child'),
|
118 |
-
'addl_css' => $this->css->get_prop('parntss'),
|
119 |
-
'imports' => $this->css->get_prop('imports'),
|
120 |
-
'rule' => $this->css->get_prop('rule'),
|
121 |
-
'sel_ndx' => $this->css->get_prop('sel_ndx'),
|
122 |
'val_qry' => array(),
|
123 |
'rule_val' => array(),
|
124 |
'sel_val' => array(),
|
125 |
'field_labels' => array(
|
126 |
-
'_background_url' => __('URL/None', 'chld_thm_cfg'),
|
127 |
-
'_background_origin' => __('Origin', 'chld_thm_cfg'),
|
128 |
-
'_background_color1' => __('Color 1', 'chld_thm_cfg'),
|
129 |
-
'_background_color2' => __('Color 2', 'chld_thm_cfg'),
|
130 |
-
'_border_width' => __('Width/None', 'chld_thm_cfg'),
|
131 |
-
'_border_style' => __('Style', 'chld_thm_cfg'),
|
132 |
-
'_border_color' => __('Color', 'chld_thm_cfg'),
|
133 |
),
|
134 |
-
'load_txt' => __('Are you sure? This will replace your current settings.', 'chld_thm_cfg'),
|
135 |
'swatch_txt' => $this->swatch_text,
|
136 |
-
'swatch_label' => __('Sample', 'chld_thm_cfg'),
|
137 |
-
'important_label' => __('<span style="font-size:10px">!</span>', 'chld_thm_cfg'),
|
138 |
-
'selector_txt' => __('Selectors', 'chld_thm_cfg'),
|
139 |
-
'close_txt' => __('Close', 'chld_thm_cfg'),
|
140 |
-
'edit_txt' => __('Edit', 'chld_thm_cfg'),
|
141 |
-
'cancel_txt' => __('Cancel', 'chld_thm_cfg'),
|
142 |
-
'rename_txt' => __('Rename', 'chld_thm_cfg'),
|
143 |
-
'css_fail_txt' => __('The stylesheet cannot be displayed.', 'chld_thm_cfg'),
|
144 |
-
'child_only_txt' => __('(Child Only)', 'chld_thm_cfg'),
|
145 |
-
'inval_theme_txt' => __('Please enter a valid Child Theme', 'chld_thm_cfg'),
|
146 |
-
'inval_name_txt' => __('Please enter a valid Child Theme name', 'chld_thm_cfg'),
|
147 |
-
'theme_exists_txt' => __('<strong>%s</strong> exists. Please enter a different Child Theme', 'chld_thm_cfg'),
|
148 |
) );
|
149 |
wp_localize_script(
|
150 |
'chld-thm-cfg-admin',
|
@@ -157,19 +157,19 @@ class ChildThemeConfiguratorAdmin {
|
|
157 |
// allows fonts and other externals to be previewed
|
158 |
// loads early not to conflict with admin stylesheets
|
159 |
$regex = "/\@import *(url)? *\( *['\"]?((https?:\/\/)?(.+?))['\"]? *\).*$/";
|
160 |
-
if ($imports = $this->css->get_prop('imports')):
|
161 |
$count = 1;
|
162 |
-
foreach ($imports as $import):
|
163 |
-
preg_match($regex, $import, $matches);
|
164 |
-
if (empty($matches[3]) && !empty($matches[4])): // relative filepath
|
165 |
$url = get_stylesheet_directory_uri();
|
166 |
-
preg_replace("#\.\./#", '', $matches[4], -1, $count);
|
167 |
-
for($i = 0; $i < $count; $i++):
|
168 |
-
$url = dirname($url);
|
169 |
endfor;
|
170 |
-
$import = preg_replace($regex, '@import url(' . trailingslashit($url) . $matches[4] . ')', $import);
|
171 |
endif;
|
172 |
-
wp_enqueue_style('chld-thm-cfg-admin' . ++$count, preg_replace($regex, "$2", $import));
|
173 |
endforeach;
|
174 |
endif;
|
175 |
}
|
@@ -179,102 +179,106 @@ class ChildThemeConfiguratorAdmin {
|
|
179 |
$this->load_config();
|
180 |
do_action( 'chld_thm_cfg_forms', $this ); // hook for custom forms
|
181 |
$this->write_config();
|
182 |
-
include_once($this->pluginPath . 'includes/class-ctc-ui.php');
|
183 |
$this->ui = new ChildThemeConfiguratorUI();
|
184 |
$this->ui->render_help_content();
|
185 |
-
add_action('admin_enqueue_scripts', array($this, 'enqueue_scripts'),999);
|
186 |
$this->load_imports();
|
187 |
}
|
188 |
|
189 |
function get_themes() {
|
190 |
// create cache of theme info
|
191 |
-
$this->themes = array('child' => array(), 'parnt' => array());
|
192 |
-
foreach (wp_get_themes() as $theme):
|
|
|
193 |
$group = $theme->parent() ? 'child' : 'parnt';
|
|
|
194 |
$slug = $theme->get_stylesheet();
|
|
|
195 |
$this->themes[$group][$slug] = array(
|
196 |
-
'Name' => $theme->get('Name'),
|
197 |
-
'Author' => $theme->get('Author'),
|
198 |
-
'Version' => $theme->get('Version'),
|
199 |
'screenshot' => $theme->get_screenshot(),
|
|
|
200 |
);
|
201 |
endforeach;
|
202 |
}
|
203 |
|
204 |
-
function validate_post($action = 'ctc_update', $noncefield = '_wpnonce') {
|
205 |
// security: request must be post, user must have permission, referrer must be local and nonce must match
|
206 |
-
return ('POST' == $_SERVER['REQUEST_METHOD']
|
207 |
-
&& current_user_can('edit_theme_options')
|
208 |
-
&& ($this->is_ajax ? check_ajax_referer( $action, $noncefield, FALSE ) : check_admin_referer($action, $noncefield, FALSE )));
|
209 |
}
|
210 |
|
211 |
function ajax_save_postdata() {
|
212 |
$this->is_ajax = TRUE;
|
213 |
-
if ($this->validate_post()):
|
214 |
$this->verify_creds();
|
215 |
$this->load_config();
|
216 |
$this->css->parse_post_data();
|
217 |
$this->css->write_css();
|
218 |
-
$result = $this->css->obj_to_utf8($this->updates);
|
219 |
$this->css->save_config();
|
220 |
// send all updates back to browser to update cache
|
221 |
-
die(json_encode($result));
|
222 |
else:
|
223 |
-
die(0);
|
224 |
endif;
|
225 |
}
|
226 |
|
227 |
function ajax_query_css() {
|
228 |
$this->is_ajax = TRUE;
|
229 |
-
if ($this->validate_post()):
|
230 |
$this->load_config();
|
231 |
$regex = "/^ctc_query_/";
|
232 |
-
foreach(preg_grep($regex, array_keys($_POST)) as $key):
|
233 |
-
$name = preg_replace($regex, '', $key);
|
234 |
-
$param[$name] = sanitize_text_field($_POST[$key]);
|
235 |
endforeach;
|
236 |
-
if (!empty($param['obj'])):
|
237 |
$result = array(
|
238 |
array(
|
239 |
-
'key' => isset($param['key'])
|
240 |
'obj' => $param['obj'],
|
241 |
-
'data' => $this->css->get_prop($param['obj'], $param),
|
242 |
),
|
243 |
);
|
244 |
-
die(json_encode($result));
|
245 |
endif;
|
246 |
endif;
|
247 |
-
die(0);
|
248 |
}
|
249 |
|
250 |
function load_config() {
|
251 |
-
include_once($this->pluginPath . 'includes/class-ctc-css.php');
|
252 |
$this->css = new ChildThemeConfiguratorCSS();
|
253 |
// if not new format or themes do not exist reinitialize
|
254 |
if ( FALSE === $this->css->read_config()
|
255 |
-
|| ! $this->check_theme_exists($this->css->get_prop('child'))
|
256 |
-
|| ! $this->check_theme_exists($this->css->get_prop('parnt')) ):
|
257 |
$this->css = new ChildThemeConfiguratorCSS();
|
258 |
$parent = get_template();
|
259 |
-
$this->css->set_prop('parnt', $parent);
|
260 |
endif;
|
261 |
-
if ('GET' == strtoupper($_SERVER['REQUEST_METHOD'])):
|
262 |
-
if ($this->css->get_prop('child')):
|
263 |
// get filesystem credentials if available
|
264 |
$this->verify_creds();
|
265 |
-
$stylesheet = $this->css->get_child_target('style.css');
|
266 |
// check file permissions
|
267 |
-
if (!is_writable($stylesheet) && !$this->fs):
|
268 |
-
add_action('admin_notices', array($this, 'writable_notice'));
|
269 |
endif;
|
270 |
// check for first run, enqueue flag will be null for anyone coming from < 1.6.0
|
271 |
-
if (!isset($this->css->enqueue))
|
272 |
-
add_action('admin_notices', array($this, 'enqueue_notice'));
|
273 |
endif;
|
274 |
// check if file ownership is messed up from old version or other plugin
|
275 |
|
276 |
-
if (fileowner($this->css->get_child_target('')) != fileowner(get_theme_root())):
|
277 |
-
add_action('admin_notices', array($this, 'owner_notice'));
|
278 |
endif;
|
279 |
endif;
|
280 |
}
|
@@ -286,36 +290,36 @@ class ChildThemeConfiguratorAdmin {
|
|
286 |
*/
|
287 |
function write_config() {
|
288 |
// make sure this is a post
|
289 |
-
if ('POST' == strtoupper($_SERVER['REQUEST_METHOD'])):
|
290 |
// see if a valid action was passed
|
291 |
-
foreach ($this->actionfields as $action):
|
292 |
if ( in_array( 'ctc_' . $action, array_keys( $_POST ) ) ):
|
293 |
$actionfield = $action;
|
294 |
break;
|
295 |
endif;
|
296 |
endforeach;
|
297 |
-
if (empty($actionfield)) return FALSE;
|
298 |
|
299 |
// make sure post passes security checkpoint
|
300 |
$this->errors = array();
|
301 |
-
if ($this->validate_post()):
|
302 |
// zip export does not require filesystem access so check that first
|
303 |
if ( 'export_child_zip' == $actionfield ):
|
304 |
$this->export_zip();
|
305 |
// if we get here the zip failed
|
306 |
-
$this->errors[] = __('Zip file creation failed.', 'chld_thm_cfg');
|
307 |
// all other actions require filesystem access
|
308 |
else:
|
309 |
// handle uploaded file before checking filesystem
|
310 |
-
if ( 'theme_image_submit' == $actionfield && isset($_FILES['ctc_theme_image'])):
|
311 |
-
$this->handle_file_upload('ctc_theme_image', $this->imgmimes);
|
312 |
-
elseif ( 'theme_screenshot_submit' == $actionfield && isset($_FILES['ctc_theme_screenshot'])):
|
313 |
-
$this->handle_file_upload('ctc_theme_screenshot', $this->imgmimes);
|
314 |
endif;
|
315 |
// now we need to check filesystem access
|
316 |
-
$args = preg_grep("/nonce/", array_keys($_POST), PREG_GREP_INVERT);
|
317 |
-
$this->verify_creds($args);
|
318 |
-
if ($this->fs):
|
319 |
$msg = FALSE;
|
320 |
// we have filesystem access so proceed with specific actions
|
321 |
switch( $actionfield ):
|
@@ -327,8 +331,8 @@ class ChildThemeConfiguratorAdmin {
|
|
327 |
case 'parnt_templates_submit':
|
328 |
// copy parent templates to child
|
329 |
if ( isset( $_POST['ctc_file_parnt'] ) ):
|
330 |
-
foreach ($_POST['ctc_file_parnt'] as $file):
|
331 |
-
$this->copy_parent_file(sanitize_text_field($file));
|
332 |
endforeach;
|
333 |
$msg = '8&tab=file_options';
|
334 |
endif;
|
@@ -337,12 +341,12 @@ class ChildThemeConfiguratorAdmin {
|
|
337 |
case 'child_templates_submit':
|
338 |
// delete child theme files
|
339 |
if ( isset( $_POST['ctc_file_child'] ) ):
|
340 |
-
if (in_array('functions', $_POST['ctc_file_child'])):
|
341 |
-
$this->errors[] = __('The Functions file is required and cannot be deleted.', 'chld_thm_cfg');
|
342 |
else:
|
343 |
-
foreach ($_POST['ctc_file_child'] as $file):
|
344 |
-
$this->delete_child_file(sanitize_text_field($file),
|
345 |
-
(0 === strpos($file, 'style') ? 'css' : 'php'));
|
346 |
endforeach;
|
347 |
$msg = '8&tab=file_options';
|
348 |
endif;
|
@@ -352,8 +356,8 @@ class ChildThemeConfiguratorAdmin {
|
|
352 |
case 'image_submit':
|
353 |
// delete child theme images
|
354 |
if ( isset( $_POST['ctc_img'] ) ):
|
355 |
-
foreach ($_POST['ctc_img'] as $file):
|
356 |
-
$this->delete_child_file('images/' . sanitize_text_field($file), 'img');
|
357 |
endforeach;
|
358 |
$msg = '8&tab=file_options';
|
359 |
endif;
|
@@ -361,9 +365,9 @@ class ChildThemeConfiguratorAdmin {
|
|
361 |
|
362 |
case 'templates_writable_submit':
|
363 |
// make specific files writable ( systems not running suExec )
|
364 |
-
if ( isset($_POST['ctc_file_child'] ) ):
|
365 |
-
foreach ($_POST['ctc_file_child'] as $file):
|
366 |
-
$this->set_writable(sanitize_text_field($file), (0 === strpos($file, 'style') ? 'css' : 'php'));
|
367 |
endforeach;
|
368 |
$msg = '8&tab=file_options';
|
369 |
endif;
|
@@ -383,22 +387,22 @@ class ChildThemeConfiguratorAdmin {
|
|
383 |
|
384 |
case 'theme_image_submit':
|
385 |
// move uploaded child theme images (now we have filesystem access)
|
386 |
-
if ( isset($_POST['movefile'] ) ):
|
387 |
-
$this->move_file_upload('images');
|
388 |
$msg = '8&tab=file_options';
|
389 |
endif;
|
390 |
break;
|
391 |
|
392 |
case 'theme_screenshot_submit':
|
393 |
// move uploaded child theme screenshot (now we have filesystem access)
|
394 |
-
if ( isset($_POST['movefile'] ) ):
|
395 |
// remove old screenshot
|
396 |
-
foreach(array_keys($this->imgmimes) as $extreg):
|
397 |
-
foreach (explode('|', $extreg) as $ext):
|
398 |
-
$this->delete_child_file('screenshot', $ext);
|
399 |
endforeach;
|
400 |
endforeach;
|
401 |
-
$this->move_file_upload('');
|
402 |
$msg = '8&tab=file_options';
|
403 |
endif;
|
404 |
break;
|
@@ -409,22 +413,22 @@ class ChildThemeConfiguratorAdmin {
|
|
409 |
endswitch;
|
410 |
endif; // end filesystem condition
|
411 |
endif; // end zip export condition
|
412 |
-
if (empty($this->errors) && empty($this->fs_prompt))
|
413 |
// no errors so we redirect with confirmation message
|
414 |
-
$this->update_redirect($msg);
|
415 |
// otherwise fail gracefully
|
416 |
$msg = NULL;
|
417 |
return FALSE;
|
418 |
endif; // end post validation condition
|
419 |
// if you end up here you are not welcome
|
420 |
$msg = NULL;
|
421 |
-
$this->errors[] = __('You do not have permission to configure child themes.', 'chld_thm_cfg');
|
422 |
endif; // end request method condition
|
423 |
return FALSE;
|
424 |
}
|
425 |
|
426 |
-
function check_theme_exists($theme) {
|
427 |
-
return in_array($theme, array_keys(wp_get_themes()));
|
428 |
}
|
429 |
|
430 |
/***
|
@@ -433,126 +437,126 @@ class ChildThemeConfiguratorAdmin {
|
|
433 |
function setup_child_theme() {
|
434 |
|
435 |
// sanitize and extract config fields into local vars
|
436 |
-
foreach ($this->configfields as $configfield):
|
437 |
-
$varparts = explode('_', $configfield);
|
438 |
-
$varname = end($varparts);
|
439 |
-
${$varname} = empty($_POST['ctc_' . $configfield]) ? '' : sanitize_text_field($_POST['ctc_' . $configfield]);
|
440 |
endforeach;
|
441 |
|
442 |
// check that all requirements are met
|
443 |
-
if ($parnt):
|
444 |
-
if (! $this->check_theme_exists($parnt)):
|
445 |
-
$this->errors[] = sprintf(__('%s does not exist. Please select a valid Parent Theme', 'chld_thm_cfg'), $parnt);
|
446 |
endif;
|
447 |
else:
|
448 |
-
$this->errors[] = __('Please select a valid Parent Theme', 'chld_thm_cfg');
|
449 |
endif;
|
450 |
// if this is a shiny brand new child theme certain rules apply
|
451 |
-
if ('new' == $type):
|
452 |
-
if (empty($template) && empty($name)):
|
453 |
-
$this->errors[] = __('Please enter a valid Child Theme template name', 'chld_thm_cfg');
|
454 |
else:
|
455 |
$configtype = 'theme'; // no custom stylesheets until style.css exists!
|
456 |
-
$child = strtolower(preg_replace("%[^\w\-]%", '', empty($template) ? $name : $template));
|
457 |
-
if ($this->check_theme_exists($child)):
|
458 |
-
$this->errors[] = sprintf(__('<strong>%s</strong> exists. Please enter a different Child Theme template name', 'chld_thm_cfg'), $child);
|
459 |
else:
|
460 |
-
add_action( 'chld_thm_cfg_addl_files', array( &$this, 'add_base_files' ), 10, 2);
|
461 |
-
add_action( 'chld_thm_cfg_addl_files', array( &$this, 'copy_screenshot' ), 10, 2);
|
462 |
-
add_action( 'chld_thm_cfg_addl_files', array( &$this, 'enqueue_parent_css' ), 15, 2);
|
463 |
endif;
|
464 |
endif;
|
465 |
// check if we have additional files from a plugin extension. if so, we have to override
|
466 |
// function to support wp_filesystem requirements
|
467 |
-
elseif (empty($configtype) || 'theme' == $configtype):
|
468 |
// no configtype means this is either from this plugin or a plugin after 1.5.0
|
469 |
-
add_action( 'chld_thm_cfg_addl_files', array( &$this, 'add_base_files' ), 10, 2);
|
470 |
-
add_action( 'chld_thm_cfg_addl_files', array( &$this, 'copy_screenshot' ), 10, 2);
|
471 |
-
add_action( 'chld_thm_cfg_addl_files', array( &$this, 'enqueue_parent_css' ), 15, 2);
|
472 |
-
elseif(has_action( 'chld_thm_cfg_addl_files' )):
|
473 |
// action exists so we have to hijack it to use new filesystem checks
|
474 |
remove_all_actions( 'chld_thm_cfg_addl_files' );
|
475 |
// back compat for plugins extension
|
476 |
-
add_action('chld_thm_cfg_addl_files', array( &$this, 'write_addl_files' ), 10, 2);
|
477 |
endif;
|
478 |
|
479 |
-
if (empty($name)):
|
480 |
-
$name = ucfirst($child);
|
481 |
endif;
|
482 |
|
483 |
-
if (empty($child)):
|
484 |
-
$this->errors[] = __('Please enter a valid Child Theme directory', 'chld_thm_cfg');
|
485 |
endif;
|
486 |
|
487 |
-
if (FALSE === $this->verify_child_dir($child)):
|
488 |
-
$this->errors[] = __('Your theme directories are not writable.', 'chld_thm_cfg');
|
489 |
-
add_action('admin_notices', array($this, 'writable_notice'));
|
490 |
endif;
|
491 |
|
492 |
// if no errors so far, we are good to create child theme
|
493 |
-
if (empty($this->errors)):
|
494 |
$this->css = new ChildThemeConfiguratorCSS();
|
495 |
-
$this->css->set_prop('parnt', $parnt);
|
496 |
-
$this->css->set_prop('child', $child);
|
497 |
-
$this->css->set_prop('child_name', $name);
|
498 |
-
$this->css->set_prop('child_author', $author);
|
499 |
-
$this->css->set_prop('child_version', strlen($version) ? $version : '1.0');
|
500 |
-
$this->css->set_prop('configtype', $configtype);
|
501 |
|
502 |
// hook for add'l plugin files and subdirectories
|
503 |
-
do_action('chld_thm_cfg_addl_files', $this);
|
504 |
|
505 |
// always parse parent stylesheet
|
506 |
-
$this->css->parse_css_file('parnt');
|
507 |
|
508 |
-
// parse child stylesheet, backup or skip (to reset)
|
509 |
-
$this->css->parse_css_file('child', $revert);
|
510 |
|
511 |
// parse additional stylesheets
|
512 |
-
if (isset($_POST['ctc_additional_css']) && is_array($_POST['ctc_additional_css'])):
|
513 |
$this->css->parentss = array();
|
514 |
-
foreach ($_POST['ctc_additional_css'] as $file):
|
515 |
-
$this->css->parse_css_file('parnt', $file);
|
516 |
$this->css->parntss[] = $file;
|
517 |
endforeach;
|
518 |
endif;
|
519 |
|
520 |
// try to write new stylsheet. If it fails send alert.
|
521 |
-
if (FALSE === $this->css->write_css(isset($_POST['ctc_backup']))):
|
522 |
-
$this->errors[] = __('Your stylesheet is not writable.', 'chld_thm_cfg');
|
523 |
-
add_action('admin_notices', array($this, 'writable_notice'));
|
524 |
return FALSE;
|
525 |
endif;
|
526 |
|
527 |
// copy parent theme mods option set
|
528 |
-
if (isset($_POST['ctc_parent_mods'])):
|
529 |
// we can copy settings from parent to child even if neither is currently active
|
530 |
// so we need cases for active parent, active child or neither
|
531 |
|
532 |
// get active theme
|
533 |
$active_theme = get_stylesheet();
|
534 |
// create temp array from parent settings
|
535 |
-
$child_mods = get_option('theme_mods_' . $parnt);
|
536 |
-
if ($active_theme == $parnt):
|
537 |
// if parent theme is active, get widgets from active sidebars_widgets array
|
538 |
$child_widgets = retrieve_widgets();
|
539 |
else:
|
540 |
// otherwise get widgets from parent theme mods
|
541 |
$child_widgets = $child_mods['sidebars_widgets']['data'];
|
542 |
endif;
|
543 |
-
if ($active_theme == $child):
|
544 |
// if child theme is active, remove widgets from temp array
|
545 |
-
unset($child_mods['sidebars_widgets']);
|
546 |
// copy temp array to child mods
|
547 |
-
update_option('theme_mods_' . $child, $child_mods);
|
548 |
// copy widgets to active sidebars_widgets array
|
549 |
-
wp_set_sidebars_widgets($child_widgets);
|
550 |
else:
|
551 |
// otherwise copy widgets to temp array with time stamp
|
552 |
$child_mods['sidebars_widgets']['data'] = $child_widgets;
|
553 |
$child_mods['sidebars_widgets']['time'] = time();
|
554 |
// copy temp array to child theme mods
|
555 |
-
update_option('theme_mods_' . $child, $child_mods);
|
556 |
endif;
|
557 |
endif;
|
558 |
|
@@ -560,75 +564,80 @@ class ChildThemeConfiguratorAdmin {
|
|
560 |
$this->css->save_config();
|
561 |
|
562 |
// hook for add'l plugin options
|
563 |
-
do_action('chld_thm_cfg_addl_options', $this); // hook for add'l plugin options
|
564 |
|
565 |
// return message id 1, which says new child theme created successfull;
|
566 |
-
return 1; //isset($_POST['ctc_scan_subdirs']) ? '9&tab=import_options' : 1;
|
567 |
endif;
|
568 |
return FALSE;
|
569 |
}
|
570 |
/*
|
571 |
* TODO: this is a stub for future use
|
572 |
*/
|
573 |
-
function sanitize_options($input) {
|
574 |
return $input;
|
575 |
}
|
576 |
|
577 |
-
function update_redirect($msg = 1) {
|
578 |
-
if (empty($this->is_ajax)):
|
579 |
-
|
|
|
|
|
|
|
|
|
|
|
580 |
die();
|
581 |
endif;
|
582 |
}
|
583 |
|
584 |
-
function verify_child_dir($path) {
|
585 |
-
if (!$this->fs) return FALSE; // return if no filesystem access
|
586 |
global $wp_filesystem;
|
587 |
-
$themedir = $wp_filesystem->find_folder(get_theme_root());
|
588 |
-
if (! $wp_filesystem->is_writable($themedir)) return FALSE;
|
589 |
-
$childparts = explode('/', $this->normalize_path($path));
|
590 |
-
while (count($childparts)):
|
591 |
-
$subdir = array_shift($childparts);
|
592 |
-
if (empty($subdir)) continue;
|
593 |
-
$themedir = trailingslashit($themedir) . $subdir;
|
594 |
-
if (! $wp_filesystem->is_dir($themedir)):
|
595 |
-
if (! $wp_filesystem->mkdir($themedir, FS_CHMOD_DIR)):
|
596 |
return FALSE;
|
597 |
endif;
|
598 |
-
elseif (! $wp_filesystem->is_writable($themedir)):
|
599 |
return FALSE;
|
600 |
endif;
|
601 |
endwhile;
|
602 |
return TRUE;
|
603 |
}
|
604 |
|
605 |
-
function add_base_files($obj){
|
606 |
// add functions.php file
|
607 |
$contents = "<?php
|
608 |
// Exit if accessed directly
|
609 |
-
if ( !defined('ABSPATH')) exit;
|
610 |
";
|
611 |
-
if (FALSE === $this->write_child_file('functions.php', $contents)
|
612 |
-
|| FALSE === $this->write_child_file('style.css', $this->css->get_css_header())) return FALSE;
|
613 |
}
|
614 |
|
615 |
function enqueue_parent_code(){
|
616 |
-
return explode("\n", apply_filters('chld_thm_cfg_enqueue_parent', "
|
617 |
-
if (!function_exists('chld_thm_cfg_parent_css')):
|
618 |
function chld_thm_cfg_parent_css() {
|
619 |
-
wp_enqueue_style('chld_thm_cfg_parent', get_template_directory_uri() . '/style.css');
|
620 |
}
|
621 |
endif;
|
622 |
-
add_action('wp_enqueue_scripts', 'chld_thm_cfg_parent_css');
|
623 |
-
"));
|
624 |
}
|
625 |
|
626 |
-
function enqueue_parent_css($obj) {
|
627 |
-
if (isset($_POST['ctc_parent_enqueue']))
|
628 |
-
$this->css->enqueue = sanitize_text_field($_POST['ctc_parent_enqueue']);
|
629 |
$marker = 'ENQUEUE PARENT ACTION';
|
630 |
$insertion = 'enqueue' == $this->css->enqueue ? $this->enqueue_parent_code() : array();
|
631 |
-
if ($filename = $this->css->is_file_ok($this->css->get_child_target('functions.php'), 'write')):
|
632 |
$this->insert_with_markers( $filename, $marker, $insertion );
|
633 |
endif;
|
634 |
}
|
@@ -638,20 +647,20 @@ add_action('wp_enqueue_scripts', 'chld_thm_cfg_parent_css');
|
|
638 |
* but it does not use wp_filesystem API!!!???
|
639 |
*/
|
640 |
function insert_with_markers( $filename, $marker, $insertion ) {
|
641 |
-
if (!$this->fs) return FALSE; // return if no filesystem access
|
642 |
global $wp_filesystem;
|
643 |
-
if(!$wp_filesystem->exists($this->fspath($filename))):
|
644 |
$markerdata = FALSE;
|
645 |
else:
|
646 |
// get_contents_array returns extra linefeeds so just split it ourself
|
647 |
-
$markerdata = explode("\n", $wp_filesystem->get_contents( $this->fspath( $filename ) ) );
|
648 |
endif;
|
649 |
$newfile = '';
|
650 |
$foundit = false;
|
651 |
if ( $markerdata ) {
|
652 |
$state = true;
|
653 |
foreach ( $markerdata as $n => $markerline ) {
|
654 |
-
if (strpos($markerline, '// BEGIN ' . $marker) !== false)
|
655 |
$state = false;
|
656 |
if ( $state ):
|
657 |
if ( $n + 1 < count( $markerdata ) )
|
@@ -659,9 +668,9 @@ add_action('wp_enqueue_scripts', 'chld_thm_cfg_parent_css');
|
|
659 |
else
|
660 |
$newfile .= "{$markerline}";
|
661 |
endif;
|
662 |
-
if (strpos($markerline, '// END ' . $marker) !== false):
|
663 |
$newfile .= "// BEGIN {$marker}\n";
|
664 |
-
if ( is_array( $insertion ))
|
665 |
foreach ( $insertion as $insertline )
|
666 |
$newfile .= "{$insertline}\n";
|
667 |
$newfile .= "// END {$marker}\n";
|
@@ -670,264 +679,264 @@ add_action('wp_enqueue_scripts', 'chld_thm_cfg_parent_css');
|
|
670 |
endif;
|
671 |
}
|
672 |
}
|
673 |
-
if (!$foundit) {
|
674 |
$newfile .= "\n// BEGIN {$marker}\n";
|
675 |
foreach ( $insertion as $insertline )
|
676 |
$newfile .= "{$insertline}\n";
|
677 |
$newfile .= "// END {$marker}\n";
|
678 |
}
|
679 |
-
if (FALSE === $wp_filesystem->put_contents($this->fspath($filename), $newfile)) return FALSE;
|
680 |
}
|
681 |
|
682 |
-
function write_child_file($file, $contents) {
|
683 |
-
if (!$this->fs) return FALSE; // return if no filesystem access
|
684 |
global $wp_filesystem;
|
685 |
-
$file = $this->fspath($this->css->is_file_ok($this->css->get_child_target($file), 'write'));
|
686 |
-
if ($file && !$wp_filesystem->exists($file)):
|
687 |
-
if (FALSE === $wp_filesystem->put_contents($file, $contents)) return FALSE;
|
688 |
endif;
|
689 |
}
|
690 |
|
691 |
-
function copy_screenshot($obj) {
|
692 |
// always copy screenshot
|
693 |
-
$this->copy_parent_file('screenshot');
|
694 |
}
|
695 |
|
696 |
-
function copy_parent_file($file, $ext = 'php') {
|
697 |
-
if (!$this->fs) return FALSE; // return if no filesystem access
|
698 |
global $wp_filesystem;
|
699 |
$parent_file = NULL;
|
700 |
-
if ('screenshot' == $file):
|
701 |
-
foreach (array_keys($this->imgmimes) as $extreg):
|
702 |
-
foreach(explode('|', $extreg) as $ext):
|
703 |
-
if ($parent_file = $this->css->is_file_ok($this->css->get_parent_source('screenshot.' . $ext))) break;
|
704 |
endforeach;
|
705 |
-
if ($parent_file):
|
706 |
-
$parent_file = $this->fspath($parent_file);
|
707 |
break;
|
708 |
endif;
|
709 |
endforeach;
|
710 |
else:
|
711 |
-
$parent_file = $this->fspath($this->css->is_file_ok($this->css->get_parent_source($file . '.' . $ext)));
|
712 |
endif;
|
713 |
-
// get child theme + file + ext (passing empty string and full child path to theme_basename )
|
714 |
-
$child_file = $this->css->get_child_target($file . '.' . $ext);
|
715 |
// return true if file already exists
|
716 |
-
if ($wp_filesystem->exists($this->fspath($child_file))) return TRUE;
|
717 |
-
$child_dir = dirname($this->theme_basename('', $child_file));
|
718 |
-
if ($parent_file // sanity check
|
719 |
&& $child_file // sanity check
|
720 |
-
&& $this->verify_child_dir($child_dir) //create child subdir if necessary
|
721 |
-
&& $wp_filesystem->copy($parent_file, $this->fspath($child_file), FS_CHMOD_FILE)) return TRUE;
|
722 |
-
$this->errors[] = __('Could not copy file.', 'chld_thm_cfg');
|
723 |
}
|
724 |
|
725 |
-
function delete_child_file($file, $ext = 'php') {
|
726 |
-
if (!$this->fs) return FALSE; // return if no filesystem access
|
727 |
global $wp_filesystem;
|
728 |
// verify file is in child theme and exists before removing.
|
729 |
-
$file = ('img' == $ext ? $file : $file . '.' . $ext);
|
730 |
-
$child_file = $this->fspath($this->css->is_file_ok($this->css->get_child_target($file), 'write'));
|
731 |
-
if ($wp_filesystem->exists($child_file)):
|
732 |
-
if (!$wp_filesystem->delete($child_file)) return FALSE;
|
733 |
endif;
|
734 |
}
|
735 |
|
736 |
-
function get_files($theme, $type = 'template') {
|
737 |
-
if (!isset($this->files[$theme])):
|
738 |
$this->files[$theme] = array();
|
739 |
-
$imgext = '(' . implode('|', array_keys($this->imgmimes)) . ')';
|
740 |
-
foreach ($this->css->recurse_directory(
|
741 |
-
trailingslashit(get_theme_root()) . $theme, '', TRUE) as $file):
|
742 |
-
$file = $this->theme_basename($theme, $file);
|
743 |
-
if (preg_match("/^style\-(\d+)\.css$/", $file, $matches)):
|
744 |
-
$date = date_i18n('D, j M Y g:i A', strtotime($matches[1]));
|
745 |
$this->files[$theme]['backup'][$file] = $date;
|
746 |
-
elseif (preg_match("/\.php$/", $file)):
|
747 |
$this->files[$theme]['template'][] = $file;
|
748 |
-
elseif (preg_match("/\.css$/", $file) && 'style.css' != $file):
|
749 |
$this->files[$theme]['stylesheet'][] = $file;
|
750 |
-
elseif (preg_match("/^images\/.+?\." . $imgext . "$/", $file)):
|
751 |
$this->files[$theme]['img'][] = $file;
|
752 |
endif;
|
753 |
endforeach;
|
754 |
endif;
|
755 |
-
return isset($this->files[$theme][$type]) ? $this->files[$theme][$type] : array();
|
756 |
}
|
757 |
|
758 |
-
function theme_basename($theme, $file) {
|
759 |
// if no theme passed, returns theme + file
|
760 |
-
$themedir = trailingslashit(get_theme_root()) . ('' == $theme ? '' : trailingslashit($theme));
|
761 |
-
return preg_replace('%^' . preg_quote($themedir) . '%', '', $file);
|
762 |
}
|
763 |
|
764 |
-
function uploads_basename($file) {
|
765 |
-
$file = $this->normalize_path($file);
|
766 |
$uplarr = wp_upload_dir();
|
767 |
-
$upldir = trailingslashit($uplarr['basedir']);
|
768 |
-
return preg_replace('%^' . preg_quote($upldir) . '%', '', $file);
|
769 |
}
|
770 |
|
771 |
-
function uploads_fullpath($file) {
|
772 |
-
$file = $this->normalize_path($file);
|
773 |
$uplarr = wp_upload_dir();
|
774 |
-
$upldir = trailingslashit($uplarr['basedir']);
|
775 |
return $upldir . $file;
|
776 |
}
|
777 |
|
778 |
function serialize_postarrays() {
|
779 |
-
foreach ($this->postarrays as $field)
|
780 |
-
if (isset($_POST[$field]) && is_array($_POST[$field]))
|
781 |
-
$_POST[$field] = implode("%%", $_POST[$field]);
|
782 |
}
|
783 |
|
784 |
function unserialize_postarrays() {
|
785 |
-
foreach ($this->postarrays as $field)
|
786 |
-
if (isset($_POST[$field]) && !is_array($_POST[$field]))
|
787 |
-
$_POST[$field] = explode("%%", $_POST[$field]);
|
788 |
}
|
789 |
|
790 |
-
function set_writable($file = NULL) {
|
791 |
|
792 |
-
$file = isset($file) ? $this->css->get_child_target($file . '.php') : apply_filters('chld_thm_cfg_target', $this->css->get_child_target(), $this->css);
|
793 |
-
if ($this->fs): // filesystem access
|
794 |
global $wp_filesystem;
|
795 |
-
if ($file && $wp_filesystem->chmod($this->fspath($file), 0666)) return;
|
796 |
endif;
|
797 |
-
$this->errors[] = __('Could not set write permissions.', 'chld_thm_cfg');
|
798 |
-
add_action('admin_notices', array($this, 'writable_notice'));
|
799 |
return FALSE;
|
800 |
}
|
801 |
|
802 |
function unset_writable() {
|
803 |
-
if (!$this->fs) return FALSE; // return if no filesystem access
|
804 |
global $wp_filesystem;
|
805 |
-
$dir = untrailingslashit($this->css->get_child_target(''));
|
806 |
-
$child = $this->theme_basename('', $dir);
|
807 |
-
$newchild = untrailingslashit($child) . '-new';
|
808 |
-
$themedir = trailingslashit(get_theme_root());
|
809 |
-
$fsthemedir = $this->fspath($themedir);
|
810 |
// is child theme owned by user?
|
811 |
-
if (fileowner($dir) == fileowner(ABSPATH)):
|
812 |
$copy = FALSE;
|
813 |
-
$wp_filesystem->chmod($dir);
|
814 |
-
// recursive chmod (as user)
|
815 |
// WP_Filesystem RECURSIVE CHMOD IS FLAWED! IT SETS ALL CHILDREN TO PERM OF OUTERMOST DIR
|
816 |
-
//if ($wp_filesystem->chmod($this->fspath($dir), FALSE, TRUE)):
|
817 |
//endif;
|
818 |
else:
|
819 |
$copy = TRUE;
|
820 |
endif;
|
821 |
-
// n -> copy entire folder (as user)
|
822 |
-
$files = $this->css->recurse_directory($dir, NULL, TRUE);
|
823 |
$errors = array();
|
824 |
-
foreach ($files as $file):
|
825 |
-
$childfile = $this->theme_basename($child, $this->normalize_path($file));
|
826 |
-
$newfile = trailingslashit($newchild) . $childfile;
|
827 |
-
$childpath = $fsthemedir . trailingslashit($child) . $childfile;
|
828 |
$newpath = $fsthemedir . $newfile;
|
829 |
-
if ($copy):
|
830 |
-
if ($this->verify_child_dir(is_dir($file)
|
831 |
-
if (is_file($file) && !$wp_filesystem->copy($childpath, $newpath)):
|
832 |
$errors[] = 'could not copy ' . $newpath;
|
833 |
endif;
|
834 |
else:
|
835 |
$errors[] = 'invalid dir: ' . $newfile;
|
836 |
endif;
|
837 |
else:
|
838 |
-
$wp_filesystem->chmod($this->fspath($file));
|
839 |
endif;
|
840 |
endforeach;
|
841 |
-
if ($copy):
|
842 |
-
// verify copy (as webserver)
|
843 |
-
$newfiles = $this->css->recurse_directory(trailingslashit($themedir) . $newchild, NULL, TRUE);
|
844 |
$deleteddirs = $deletedfiles = 0;
|
845 |
-
if (count($newfiles) == count($files)):
|
846 |
-
// rename old (as webserver)
|
847 |
-
if (!$wp_filesystem->exists(trailingslashit($fsthemedir) . $child . '-old'))
|
848 |
-
$wp_filesystem->move(trailingslashit($fsthemedir) . $child, trailingslashit($fsthemedir) . $child . '-old');
|
849 |
-
// rename new (as user)
|
850 |
-
if (!$wp_filesystem->exists(trailingslashit($fsthemedir) . $child))
|
851 |
-
$wp_filesystem->move(trailingslashit($fsthemedir) . $newchild, trailingslashit($fsthemedir) . $child);
|
852 |
-
// remove old files (as webserver)
|
853 |
-
$oldfiles = $this->css->recurse_directory(trailingslashit($themedir) . $child . '-old', NULL, TRUE);
|
854 |
-
array_unshift($oldfiles, trailingslashit($themedir) . $child . '-old');
|
855 |
-
foreach (array_reverse($oldfiles) as $file):
|
856 |
-
if ($wp_filesystem->delete($this->fspath($file)) || (is_dir($file) && @rmdir($file)) || (is_file($file) && @unlink($file))):
|
857 |
$deletedfiles++;
|
858 |
endif;
|
859 |
endforeach;
|
860 |
-
if ($deletedfiles != count($oldfiles)):
|
861 |
-
$errors[] = 'deleted: ' . $deletedfiles . ' != ' . count($oldfiles) . ' files';
|
862 |
endif;
|
863 |
else:
|
864 |
$errors[] = 'newfiles != files';
|
865 |
endif;
|
866 |
endif;
|
867 |
-
if (count($errors)):
|
868 |
-
$this->errors[] = __('There were errors while resetting permissions.', 'chld_thm_cfg') ;
|
869 |
-
add_action('admin_notices', array($this, 'writable_notice'));
|
870 |
endif;
|
871 |
}
|
872 |
|
873 |
-
function handle_file_upload($field, $childdir = NULL, $mimes = NULL){
|
874 |
$uploadedfile = $_FILES[$field];
|
875 |
$upload_overrides = array(
|
876 |
'test_form' => FALSE,
|
877 |
-
'mimes' => (is_array($mimes) ? $mimes : NULL)
|
878 |
);
|
879 |
if ( ! function_exists( 'wp_handle_upload' ) ) require_once( ABSPATH . 'wp-admin/includes/file.php' );
|
880 |
$movefile = wp_handle_upload( $uploadedfile, $upload_overrides );
|
881 |
-
if (isset($movefile['error'])):
|
882 |
$this->errors[] = $movefile['error'];
|
883 |
return FALSE;
|
884 |
endif;
|
885 |
-
$_POST['movefile'] = $this->uploads_basename($movefile['file']);
|
886 |
}
|
887 |
|
888 |
-
function move_file_upload($subdir = 'images') {
|
889 |
-
if (!$this->fs) return FALSE; // return if no filesystem access
|
890 |
global $wp_filesystem;
|
891 |
-
$source_file = sanitize_text_field($_POST['movefile']);
|
892 |
-
$target_file = ('' == $subdir ?
|
893 |
-
preg_replace("%^.+(\.\w+)$%", "screenshot$1", basename($source_file)) :
|
894 |
-
trailingslashit($subdir) . basename($source_file));
|
895 |
-
if (FALSE !== $this->verify_child_dir(trailingslashit($this->css->get_prop('child')) . $subdir)):
|
896 |
-
$source_path = $this->fspath($this->uploads_fullpath($source_file));
|
897 |
-
if ($target_path = $this->css->is_file_ok($this->css->get_child_target($target_file), 'write')):
|
898 |
-
$target_path = $this->fspath($target_path);
|
899 |
-
if ($wp_filesystem->exists($source_path)):
|
900 |
-
if ($wp_filesystem->move($source_path, $target_path)) return TRUE;
|
901 |
endif;
|
902 |
endif;
|
903 |
endif;
|
904 |
|
905 |
-
$this->errors[] = __('Could not upload file.', 'chld_thm_cfg');
|
906 |
}
|
907 |
|
908 |
function export_zip() {
|
909 |
-
if (($child = $this->css->get_prop('child'))
|
910 |
-
&& ($dir = $this->css->is_file_ok(dirname($this->css->get_child_target()), 'search'))
|
911 |
-
&& ($version = preg_replace("%[^\w\.\-]%", '', $this->css->get_prop('version')))):
|
912 |
// use php system upload dir to store temp files so that we can use pclzip
|
913 |
-
$tmpdir = ini_get('upload_tmp_dir') ? ini_get('upload_tmp_dir') : sys_get_temp_dir();
|
914 |
-
$file = trailingslashit($tmpdir) . $child . '-' . $version . '.zip';
|
915 |
mbstring_binary_safe_encoding();
|
916 |
|
917 |
-
require_once(ABSPATH . 'wp-admin/includes/class-pclzip.php');
|
918 |
|
919 |
-
$archive = new PclZip($file);
|
920 |
-
if ($archive->create($dir, PCLZIP_OPT_REMOVE_PATH, dirname($dir)) == 0) return FALSE;
|
921 |
reset_mbstring_encoding();
|
922 |
header( 'Content-Description: File Transfer' );
|
923 |
header( 'Content-Type: application/octet-stream' );
|
924 |
-
header( 'Content-Length: ' . filesize($file) );
|
925 |
-
header( 'Content-Disposition: attachment; filename=' . basename($file) );
|
926 |
-
header( 'Expires: 0');
|
927 |
-
header( 'Cache-Control: must-revalidate');
|
928 |
-
header( 'Pragma: public');
|
929 |
-
readfile($file);
|
930 |
-
unlink($file);
|
931 |
die();
|
932 |
endif;
|
933 |
}
|
@@ -935,22 +944,24 @@ add_action('wp_enqueue_scripts', 'chld_thm_cfg_parent_css');
|
|
935 |
/*
|
936 |
*
|
937 |
*/
|
938 |
-
function verify_creds($args = array()) {
|
939 |
$this->fs_prompt = $this->fs = FALSE;
|
940 |
//fs prompt does not support arrays as post data - serialize arrays
|
941 |
$this->serialize_postarrays();
|
942 |
// generate callback url
|
943 |
-
$url =
|
|
|
|
|
944 |
// buffer output so we can process prior to http header
|
945 |
ob_start();
|
946 |
-
if ($creds = request_filesystem_credentials($
|
947 |
// check filesystem permission if direct or ftp creds exist
|
948 |
-
if ( WP_Filesystem($creds) )
|
949 |
// login ok
|
950 |
$this->fs = TRUE;
|
951 |
else
|
952 |
// incorrect credentials, get form with error flag
|
953 |
-
$creds = request_filesystem_credentials($
|
954 |
else:
|
955 |
// no credentials, initialize unpriveledged filesystem object
|
956 |
WP_Filesystem();
|
@@ -966,33 +977,33 @@ add_action('wp_enqueue_scripts', 'chld_thm_cfg_parent_css');
|
|
966 |
/*
|
967 |
* convert 'direct' filepath into wp_filesystem filepath
|
968 |
*/
|
969 |
-
function fspath($file){
|
970 |
-
if (! $this->fs) return FALSE; // return if no filesystem access
|
971 |
global $wp_filesystem;
|
972 |
-
if (is_dir($file)):
|
973 |
$dir = $file;
|
974 |
$base = '';
|
975 |
else:
|
976 |
-
$dir = dirname($file);
|
977 |
-
$base = basename($file);
|
978 |
endif;
|
979 |
-
$fsdir = $wp_filesystem->find_folder($dir);
|
980 |
-
return trailingslashit($fsdir) . $base;
|
981 |
}
|
982 |
|
983 |
function writable_notice() {
|
984 |
?> <div class="update-nag">
|
985 |
-
<p><?php _e( 'Child Theme Configurator is unable to write to the stylesheet. This can be resolved using one of the following options:<ol>', 'chld_thm_cfg');
|
986 |
-
if (isset($_SERVER['SERVER_SOFTWARE']) && preg_match('%unix%i',$_SERVER['SERVER_SOFTWARE'])):
|
987 |
-
_e('<li>Temporarily make the stylesheet writable by clicking the button below. You should change this back when you are finished editing for security by clicking "Make read-only" under the "Files" tab.</li>', 'chld_thm_cfg');
|
988 |
?><form action="?page=<?php echo CHLD_THM_CFG_MENU; ?>" method="post"><?php wp_nonce_field( 'ctc_update' ); ?>
|
989 |
-
<input name="ctc_set_writable" class="button" type="submit" value="<?php _e('Temporarily make stylesheet writable', 'chld_thm_cfg'); ?>"/></form><?php endif;
|
990 |
-
_e('<li><a target="_blank" href="http://codex.wordpress.org/Editing_wp-config.php#WordPress_Upgrade_Constants" title="Editin wp-config.php">Add your FTP/SSH credentials to the WordPress config file</a>.</li>', 'chld_thm_cfg');
|
991 |
-
if (isset($_SERVER['SERVER_SOFTWARE']) && preg_match('%iis%i',$_SERVER['SERVER_SOFTWARE']))
|
992 |
-
_e('<li><a target="_blank" href="http://technet.microsoft.com/en-us/library/cc771170" title="Setting Application Pool Identity">Assign WordPress to an application pool that has write permissions</a> (Windows IIS systems).</li>', 'chld_thm_cfg');
|
993 |
-
_e('<li><a target="_blank" href="http://codex.wordpress.org/Changing_File_Permissions" title="Changing File Permissions">Set the stylesheet write permissions on the server manually</a> (not recommended).</li>', 'chld_thm_cfg');
|
994 |
-
if (isset($_SERVER['SERVER_SOFTWARE']) && preg_match('%unix%i',$_SERVER['SERVER_SOFTWARE']))
|
995 |
-
_e('<li>Run PHP under Apache with suEXEC (contact your web host).</li>', 'chld_thm_cfg') ?>
|
996 |
</ol></p>
|
997 |
</div>
|
998 |
<?php
|
@@ -1000,45 +1011,45 @@ add_action('wp_enqueue_scripts', 'chld_thm_cfg_parent_css');
|
|
1000 |
function owner_notice() {
|
1001 |
?>
|
1002 |
<div class="update-nag">
|
1003 |
-
<p><?php _e( 'This Child Theme is not owned by your website account. It may have been created by a prior version of this plugin or by another program. Moving forward, it must be owned by your website account to make changes. Child Theme Configurator will attempt to correct this when you click the button below.', 'chld_thm_cfg') ?></p>
|
1004 |
<form action="?page=<?php echo CHLD_THM_CFG_MENU; ?>" method="post"><?php wp_nonce_field( 'ctc_update' ); ?>
|
1005 |
-
<input name="ctc_reset_permission" class="button" type="submit" value="<?php _e('Correct Child Theme Permissions', 'chld_thm_cfg'); ?>"/></form> </div>
|
1006 |
<?php
|
1007 |
}
|
1008 |
|
1009 |
function enqueue_notice() {
|
1010 |
?>
|
1011 |
<div class="update-nag">
|
1012 |
-
<p><?php _e( 'Child Theme Configurator has changed the way it handles the parent stylesheet. Please set your preferences below and click "Generate Child Theme Files" to update your configuration.', 'chld_thm_cfg') ?></p>
|
1013 |
</div>
|
1014 |
<?php
|
1015 |
}
|
1016 |
|
1017 |
// back compatibility function for plugins extension
|
1018 |
-
function write_addl_files($chld_thm_cfg) {
|
1019 |
global $chld_thm_cfg_plugins;
|
1020 |
-
if (!is_object($chld_thm_cfg_plugins) || !$chld_thm_cfg->fs) return FALSE;
|
1021 |
-
$configtype = $chld_thm_cfg->css->get_prop('configtype');
|
1022 |
-
if ('theme' == $configtype || !($def = $chld_thm_cfg_plugins->defs->get_def($configtype))) return FALSE;
|
1023 |
-
$child = trailingslashit($chld_thm_cfg->css->get_prop('child'));
|
1024 |
-
if (isset($def['addl']) && is_array($def['addl']) && count($def['addl'])):
|
1025 |
-
foreach ($def['addl'] as $path => $type):
|
1026 |
|
1027 |
// sanitize the crap out of the target data -- it will be used to create paths
|
1028 |
-
$path = $this->normalize_path(preg_replace("%[^\w\\//\-]%", '', sanitize_text_field($child . $path)));
|
1029 |
-
if (('dir' == $type && FALSE === $chld_thm_cfg->verify_child_dir($path))
|
1030 |
-
|| ('dir' != $type && FALSE === $chld_thm_cfg->write_child_file($path, ''))):
|
1031 |
$chld_thm_cfg->errors[] =
|
1032 |
-
__('Your theme directories are not writable.', 'chld_thm_cfg_plugins');
|
1033 |
endif;
|
1034 |
endforeach;
|
1035 |
endif;
|
1036 |
// write main def file
|
1037 |
-
if (isset($def['target'])):
|
1038 |
-
$path = $this->normalize_path(preg_replace("%[^\w\\//\-\.]%", '', sanitize_text_field($def['target']))); //$child .
|
1039 |
-
if (FALSE === $chld_thm_cfg->write_child_file($path, '')):
|
1040 |
$chld_thm_cfg->errors[] =
|
1041 |
-
__('Your stylesheet is not writable.', 'chld_thm_cfg_plugins');
|
1042 |
return FALSE;
|
1043 |
endif;
|
1044 |
endif;
|
1 |
<?php
|
2 |
// Exit if accessed directly
|
3 |
+
if ( !defined( 'ABSPATH' ) ) exit;
|
4 |
|
5 |
/*
|
6 |
Class: Child_Theme_Configurator
|
7 |
Plugin URI: http://www.lilaeamedia.com/plugins/child-theme-configurator/
|
8 |
Description: Main Controller Class
|
9 |
+
Version: 1.6.3
|
10 |
Author: Lilaea Media
|
11 |
Author URI: http://www.lilaeamedia.com/
|
12 |
Text Domain: chld_thm_cfg
|
13 |
Domain Path: /lang
|
14 |
License: GPLv2
|
15 |
+
Copyright (C) 2014-2015 Lilaea Media
|
16 |
*/
|
17 |
class ChildThemeConfiguratorAdmin {
|
18 |
|
79 |
var $cache_updates = TRUE;
|
80 |
var $swatch_text = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.';
|
81 |
|
82 |
+
function __construct( $file ) {
|
83 |
$this->pluginPath = trailingslashit( dirname( $file ) );
|
84 |
+
$this->pluginURL = plugin_dir_url( $file );
|
85 |
$this->menuName = CHLD_THM_CFG_MENU; // backward compatability for plugins extension
|
86 |
}
|
87 |
function render() {
|
88 |
$this->ui->render();
|
89 |
}
|
90 |
function enqueue_scripts() {
|
91 |
+
wp_enqueue_style( 'chld-thm-cfg-admin', $this->pluginURL . 'css/chld-thm-cfg.css', array(), '1.6.3' );
|
92 |
|
93 |
// we need to use local jQuery UI Widget/Menu/Selectmenu 1.11.2 because selectmenu is not included in < 1.11.2
|
94 |
// this will be updated in a later release to use WP Core scripts when it is widely adopted
|
95 |
+
if ( !wp_script_is( 'jquery-ui-selectmenu', 'registered' ) ): // selectmenu.min.js
|
96 |
+
wp_enqueue_script( 'jquery-ui-selectmenu', $this->pluginURL . 'js/selectmenu.min.js', array( 'jquery','jquery-ui-core','jquery-ui-position' ), FALSE, TRUE );
|
97 |
endif;
|
98 |
+
wp_enqueue_script( 'ctc-thm-cfg-ctcgrad', $this->pluginURL . 'js/ctcgrad.min.js', array( 'jquery' ), FALSE, TRUE );
|
99 |
+
wp_enqueue_script( 'chld-thm-cfg-admin', $this->pluginURL . 'js/chld-thm-cfg.min.js',
|
100 |
array(
|
101 |
'jquery-ui-autocomplete',
|
102 |
'jquery-ui-selectmenu',
|
103 |
'wp-color-picker',
|
104 |
), FALSE, TRUE );
|
105 |
+
$localize_array = apply_filters( 'chld_thm_cfg_localize_script', array(
|
106 |
'ssl' => is_ssl(),
|
107 |
'homeurl' => get_home_url(),
|
108 |
'ajaxurl' => admin_url( 'admin-ajax.php' ),
|
109 |
'theme_uri' => get_theme_root_uri(),
|
110 |
'page' => CHLD_THM_CFG_MENU,
|
111 |
'themes' => $this->themes,
|
112 |
+
'source' => apply_filters( 'chld_thm_cfg_source_uri', get_theme_root_uri() . '/'
|
113 |
+
. $this->css->get_prop( 'parnt' ) . '/style.css', $this->css ),
|
114 |
+
'target' => apply_filters( 'chld_thm_cfg_target_uri', get_theme_root_uri() . '/'
|
115 |
+
. $this->css->get_prop( 'child' ) . '/style.css', $this->css ),
|
116 |
+
'parnt' => $this->css->get_prop( 'parnt' ),
|
117 |
+
'child' => $this->css->get_prop( 'child' ),
|
118 |
+
'addl_css' => $this->css->get_prop( 'parntss' ),
|
119 |
+
'imports' => $this->css->get_prop( 'imports' ),
|
120 |
+
'rule' => $this->css->get_prop( 'rule' ),
|
121 |
+
'sel_ndx' => $this->css->get_prop( 'sel_ndx' ),
|
122 |
'val_qry' => array(),
|
123 |
'rule_val' => array(),
|
124 |
'sel_val' => array(),
|
125 |
'field_labels' => array(
|
126 |
+
'_background_url' => __( 'URL/None', 'chld_thm_cfg' ),
|
127 |
+
'_background_origin' => __( 'Origin', 'chld_thm_cfg' ),
|
128 |
+
'_background_color1' => __( 'Color 1', 'chld_thm_cfg' ),
|
129 |
+
'_background_color2' => __( 'Color 2', 'chld_thm_cfg' ),
|
130 |
+
'_border_width' => __( 'Width/None', 'chld_thm_cfg' ),
|
131 |
+
'_border_style' => __( 'Style', 'chld_thm_cfg' ),
|
132 |
+
'_border_color' => __( 'Color', 'chld_thm_cfg' ),
|
133 |
),
|
134 |
+
'load_txt' => __( 'Are you sure? This will replace your current settings.', 'chld_thm_cfg' ),
|
135 |
'swatch_txt' => $this->swatch_text,
|
136 |
+
'swatch_label' => __( 'Sample', 'chld_thm_cfg' ),
|
137 |
+
'important_label' => __( '<span style="font-size:10px">!</span>', 'chld_thm_cfg' ),
|
138 |
+
'selector_txt' => __( 'Selectors', 'chld_thm_cfg' ),
|
139 |
+
'close_txt' => __( 'Close', 'chld_thm_cfg' ),
|
140 |
+
'edit_txt' => __( 'Edit', 'chld_thm_cfg' ),
|
141 |
+
'cancel_txt' => __( 'Cancel', 'chld_thm_cfg' ),
|
142 |
+
'rename_txt' => __( 'Rename', 'chld_thm_cfg' ),
|
143 |
+
'css_fail_txt' => __( 'The stylesheet cannot be displayed.', 'chld_thm_cfg' ),
|
144 |
+
'child_only_txt' => __( '(Child Only)', 'chld_thm_cfg' ),
|
145 |
+
'inval_theme_txt' => __( 'Please enter a valid Child Theme', 'chld_thm_cfg' ),
|
146 |
+
'inval_name_txt' => __( 'Please enter a valid Child Theme name', 'chld_thm_cfg' ),
|
147 |
+
'theme_exists_txt' => __( '<strong>%s</strong> exists. Please enter a different Child Theme', 'chld_thm_cfg' ),
|
148 |
) );
|
149 |
wp_localize_script(
|
150 |
'chld-thm-cfg-admin',
|
157 |
// allows fonts and other externals to be previewed
|
158 |
// loads early not to conflict with admin stylesheets
|
159 |
$regex = "/\@import *(url)? *\( *['\"]?((https?:\/\/)?(.+?))['\"]? *\).*$/";
|
160 |
+
if ( $imports = $this->css->get_prop( 'imports' ) ):
|
161 |
$count = 1;
|
162 |
+
foreach ( $imports as $import ):
|
163 |
+
preg_match( $regex, $import, $matches );
|
164 |
+
if ( empty( $matches[3] ) && !empty( $matches[4] ) ): // relative filepath
|
165 |
$url = get_stylesheet_directory_uri();
|
166 |
+
preg_replace( "#\.\./#", '', $matches[4], -1, $count );
|
167 |
+
for( $i = 0; $i < $count; $i++ ):
|
168 |
+
$url = dirname( $url );
|
169 |
endfor;
|
170 |
+
$import = preg_replace( $regex, '@import url(' . trailingslashit( $url ) . $matches[4] . ')', $import );
|
171 |
endif;
|
172 |
+
wp_enqueue_style( 'chld-thm-cfg-admin' . ++$count, preg_replace( $regex, "$2", $import ) );
|
173 |
endforeach;
|
174 |
endif;
|
175 |
}
|
179 |
$this->load_config();
|
180 |
do_action( 'chld_thm_cfg_forms', $this ); // hook for custom forms
|
181 |
$this->write_config();
|
182 |
+
include_once( $this->pluginPath . 'includes/class-ctc-ui.php' );
|
183 |
$this->ui = new ChildThemeConfiguratorUI();
|
184 |
$this->ui->render_help_content();
|
185 |
+
add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_scripts' ),999 );
|
186 |
$this->load_imports();
|
187 |
}
|
188 |
|
189 |
function get_themes() {
|
190 |
// create cache of theme info
|
191 |
+
$this->themes = array( 'child' => array(), 'parnt' => array() );
|
192 |
+
foreach ( wp_get_themes() as $theme ):
|
193 |
+
// organize into parent and child themes
|
194 |
$group = $theme->parent() ? 'child' : 'parnt';
|
195 |
+
// get the theme slug
|
196 |
$slug = $theme->get_stylesheet();
|
197 |
+
// add theme to themes array
|
198 |
$this->themes[$group][$slug] = array(
|
199 |
+
'Name' => $theme->get( 'Name' ),
|
200 |
+
'Author' => $theme->get( 'Author' ),
|
201 |
+
'Version' => $theme->get( 'Version' ),
|
202 |
'screenshot' => $theme->get_screenshot(),
|
203 |
+
'allowed' => $theme->is_allowed(),
|
204 |
);
|
205 |
endforeach;
|
206 |
}
|
207 |
|
208 |
+
function validate_post( $action = 'ctc_update', $noncefield = '_wpnonce' ) {
|
209 |
// security: request must be post, user must have permission, referrer must be local and nonce must match
|
210 |
+
return ( 'POST' == $_SERVER['REQUEST_METHOD']
|
211 |
+
&& current_user_can( 'install_themes' ) // ( 'edit_theme_options' )
|
212 |
+
&& ( $this->is_ajax ? check_ajax_referer( $action, $noncefield, FALSE ) : check_admin_referer( $action, $noncefield, FALSE ) ) );
|
213 |
}
|
214 |
|
215 |
function ajax_save_postdata() {
|
216 |
$this->is_ajax = TRUE;
|
217 |
+
if ( $this->validate_post() ):
|
218 |
$this->verify_creds();
|
219 |
$this->load_config();
|
220 |
$this->css->parse_post_data();
|
221 |
$this->css->write_css();
|
222 |
+
$result = $this->css->obj_to_utf8( $this->updates );
|
223 |
$this->css->save_config();
|
224 |
// send all updates back to browser to update cache
|
225 |
+
die( json_encode( $result ) );
|
226 |
else:
|
227 |
+
die( 0 );
|
228 |
endif;
|
229 |
}
|
230 |
|
231 |
function ajax_query_css() {
|
232 |
$this->is_ajax = TRUE;
|
233 |
+
if ( $this->validate_post() ):
|
234 |
$this->load_config();
|
235 |
$regex = "/^ctc_query_/";
|
236 |
+
foreach( preg_grep( $regex, array_keys( $_POST ) ) as $key ):
|
237 |
+
$name = preg_replace( $regex, '', $key );
|
238 |
+
$param[$name] = sanitize_text_field( $_POST[$key] );
|
239 |
endforeach;
|
240 |
+
if ( !empty( $param['obj'] ) ):
|
241 |
$result = array(
|
242 |
array(
|
243 |
+
'key' => isset( $param['key'] ) ? $param['key'] : '',
|
244 |
'obj' => $param['obj'],
|
245 |
+
'data' => $this->css->get_prop( $param['obj'], $param ),
|
246 |
),
|
247 |
);
|
248 |
+
die( json_encode( $result ) );
|
249 |
endif;
|
250 |
endif;
|
251 |
+
die( 0 );
|
252 |
}
|
253 |
|
254 |
function load_config() {
|
255 |
+
include_once( $this->pluginPath . 'includes/class-ctc-css.php' );
|
256 |
$this->css = new ChildThemeConfiguratorCSS();
|
257 |
// if not new format or themes do not exist reinitialize
|
258 |
if ( FALSE === $this->css->read_config()
|
259 |
+
|| ! $this->check_theme_exists( $this->css->get_prop( 'child' ) )
|
260 |
+
|| ! $this->check_theme_exists( $this->css->get_prop( 'parnt' ) ) ):
|
261 |
$this->css = new ChildThemeConfiguratorCSS();
|
262 |
$parent = get_template();
|
263 |
+
$this->css->set_prop( 'parnt', $parent );
|
264 |
endif;
|
265 |
+
if ( 'GET' == strtoupper( $_SERVER['REQUEST_METHOD'] ) ):
|
266 |
+
if ( $this->css->get_prop( 'child' ) ):
|
267 |
// get filesystem credentials if available
|
268 |
$this->verify_creds();
|
269 |
+
$stylesheet = $this->css->get_child_target( 'style.css' );
|
270 |
// check file permissions
|
271 |
+
if ( !is_writable( $stylesheet ) && !$this->fs ):
|
272 |
+
add_action( 'admin_notices', array( $this, 'writable_notice' ) );
|
273 |
endif;
|
274 |
// check for first run, enqueue flag will be null for anyone coming from < 1.6.0
|
275 |
+
if ( !isset( $this->css->enqueue ) )
|
276 |
+
add_action( 'admin_notices', array( $this, 'enqueue_notice' ) );
|
277 |
endif;
|
278 |
// check if file ownership is messed up from old version or other plugin
|
279 |
|
280 |
+
if ( fileowner( $this->css->get_child_target( '' ) ) != fileowner( get_theme_root() ) ):
|
281 |
+
add_action( 'admin_notices', array( $this, 'owner_notice' ) );
|
282 |
endif;
|
283 |
endif;
|
284 |
}
|
290 |
*/
|
291 |
function write_config() {
|
292 |
// make sure this is a post
|
293 |
+
if ( 'POST' == strtoupper( $_SERVER['REQUEST_METHOD'] ) ):
|
294 |
// see if a valid action was passed
|
295 |
+
foreach ( $this->actionfields as $action ):
|
296 |
if ( in_array( 'ctc_' . $action, array_keys( $_POST ) ) ):
|
297 |
$actionfield = $action;
|
298 |
break;
|
299 |
endif;
|
300 |
endforeach;
|
301 |
+
if ( empty( $actionfield ) ) return FALSE;
|
302 |
|
303 |
// make sure post passes security checkpoint
|
304 |
$this->errors = array();
|
305 |
+
if ( $this->validate_post() ):
|
306 |
// zip export does not require filesystem access so check that first
|
307 |
if ( 'export_child_zip' == $actionfield ):
|
308 |
$this->export_zip();
|
309 |
// if we get here the zip failed
|
310 |
+
$this->errors[] = __( 'Zip file creation failed.', 'chld_thm_cfg' );
|
311 |
// all other actions require filesystem access
|
312 |
else:
|
313 |
// handle uploaded file before checking filesystem
|
314 |
+
if ( 'theme_image_submit' == $actionfield && isset( $_FILES['ctc_theme_image'] ) ):
|
315 |
+
$this->handle_file_upload( 'ctc_theme_image', $this->imgmimes );
|
316 |
+
elseif ( 'theme_screenshot_submit' == $actionfield && isset( $_FILES['ctc_theme_screenshot'] ) ):
|
317 |
+
$this->handle_file_upload( 'ctc_theme_screenshot', $this->imgmimes );
|
318 |
endif;
|
319 |
// now we need to check filesystem access
|
320 |
+
$args = preg_grep( "/nonce/", array_keys( $_POST ), PREG_GREP_INVERT );
|
321 |
+
$this->verify_creds( $args );
|
322 |
+
if ( $this->fs ):
|
323 |
$msg = FALSE;
|
324 |
// we have filesystem access so proceed with specific actions
|
325 |
switch( $actionfield ):
|
331 |
case 'parnt_templates_submit':
|
332 |
// copy parent templates to child
|
333 |
if ( isset( $_POST['ctc_file_parnt'] ) ):
|
334 |
+
foreach ( $_POST['ctc_file_parnt'] as $file ):
|
335 |
+
$this->copy_parent_file( sanitize_text_field( $file ) );
|
336 |
endforeach;
|
337 |
$msg = '8&tab=file_options';
|
338 |
endif;
|
341 |
case 'child_templates_submit':
|
342 |
// delete child theme files
|
343 |
if ( isset( $_POST['ctc_file_child'] ) ):
|
344 |
+
if ( in_array( 'functions', $_POST['ctc_file_child'] ) ):
|
345 |
+
$this->errors[] = __( 'The Functions file is required and cannot be deleted.', 'chld_thm_cfg' );
|
346 |
else:
|
347 |
+
foreach ( $_POST['ctc_file_child'] as $file ):
|
348 |
+
$this->delete_child_file( sanitize_text_field( $file ),
|
349 |
+
( 0 === strpos( $file, 'style' ) ? 'css' : 'php' ) );
|
350 |
endforeach;
|
351 |
$msg = '8&tab=file_options';
|
352 |
endif;
|
356 |
case 'image_submit':
|
357 |
// delete child theme images
|
358 |
if ( isset( $_POST['ctc_img'] ) ):
|
359 |
+
foreach ( $_POST['ctc_img'] as $file ):
|
360 |
+
$this->delete_child_file( 'images/' . sanitize_text_field( $file ), 'img' );
|
361 |
endforeach;
|
362 |
$msg = '8&tab=file_options';
|
363 |
endif;
|
365 |
|
366 |
case 'templates_writable_submit':
|
367 |
// make specific files writable ( systems not running suExec )
|
368 |
+
if ( isset( $_POST['ctc_file_child'] ) ):
|
369 |
+
foreach ( $_POST['ctc_file_child'] as $file ):
|
370 |
+
$this->set_writable( sanitize_text_field( $file ), ( 0 === strpos( $file, 'style' ) ? 'css' : 'php' ) );
|
371 |
endforeach;
|
372 |
$msg = '8&tab=file_options';
|
373 |
endif;
|
387 |
|
388 |
case 'theme_image_submit':
|
389 |
// move uploaded child theme images (now we have filesystem access)
|
390 |
+
if ( isset( $_POST['movefile'] ) ):
|
391 |
+
$this->move_file_upload( 'images' );
|
392 |
$msg = '8&tab=file_options';
|
393 |
endif;
|
394 |
break;
|
395 |
|
396 |
case 'theme_screenshot_submit':
|
397 |
// move uploaded child theme screenshot (now we have filesystem access)
|
398 |
+
if ( isset( $_POST['movefile'] ) ):
|
399 |
// remove old screenshot
|
400 |
+
foreach( array_keys( $this->imgmimes ) as $extreg ):
|
401 |
+
foreach ( explode( '|', $extreg ) as $ext ):
|
402 |
+
$this->delete_child_file( 'screenshot', $ext );
|
403 |
endforeach;
|
404 |
endforeach;
|
405 |
+
$this->move_file_upload( '' );
|
406 |
$msg = '8&tab=file_options';
|
407 |
endif;
|
408 |
break;
|
413 |
endswitch;
|
414 |
endif; // end filesystem condition
|
415 |
endif; // end zip export condition
|
416 |
+
if ( empty( $this->errors ) && empty( $this->fs_prompt ) )
|
417 |
// no errors so we redirect with confirmation message
|
418 |
+
$this->update_redirect( $msg );
|
419 |
// otherwise fail gracefully
|
420 |
$msg = NULL;
|
421 |
return FALSE;
|
422 |
endif; // end post validation condition
|
423 |
// if you end up here you are not welcome
|
424 |
$msg = NULL;
|
425 |
+
$this->errors[] = __( 'You do not have permission to configure child themes.', 'chld_thm_cfg' );
|
426 |
endif; // end request method condition
|
427 |
return FALSE;
|
428 |
}
|
429 |
|
430 |
+
function check_theme_exists( $theme ) {
|
431 |
+
return in_array( $theme, array_keys( wp_get_themes() ) );
|
432 |
}
|
433 |
|
434 |
/***
|
437 |
function setup_child_theme() {
|
438 |
|
439 |
// sanitize and extract config fields into local vars
|
440 |
+
foreach ( $this->configfields as $configfield ):
|
441 |
+
$varparts = explode( '_', $configfield );
|
442 |
+
$varname = end( $varparts );
|
443 |
+
${$varname} = empty( $_POST['ctc_' . $configfield] ) ? '' : sanitize_text_field( $_POST['ctc_' . $configfield] );
|
444 |
endforeach;
|
445 |
|
446 |
// check that all requirements are met
|
447 |
+
if ( $parnt ):
|
448 |
+
if ( ! $this->check_theme_exists( $parnt ) ):
|
449 |
+
$this->errors[] = sprintf( __( '%s does not exist. Please select a valid Parent Theme', 'chld_thm_cfg' ), $parnt );
|
450 |
endif;
|
451 |
else:
|
452 |
+
$this->errors[] = __( 'Please select a valid Parent Theme', 'chld_thm_cfg' );
|
453 |
endif;
|
454 |
// if this is a shiny brand new child theme certain rules apply
|
455 |
+
if ( 'new' == $type ):
|
456 |
+
if ( empty( $template ) && empty( $name ) ):
|
457 |
+
$this->errors[] = __( 'Please enter a valid Child Theme template name', 'chld_thm_cfg' );
|
458 |
else:
|
459 |
$configtype = 'theme'; // no custom stylesheets until style.css exists!
|
460 |
+
$child = strtolower( preg_replace( "%[^\w\-]%", '', empty( $template ) ? $name : $template ) );
|
461 |
+
if ( $this->check_theme_exists( $child ) ):
|
462 |
+
$this->errors[] = sprintf( __( '<strong>%s</strong> exists. Please enter a different Child Theme template name', 'chld_thm_cfg' ), $child );
|
463 |
else:
|
464 |
+
add_action( 'chld_thm_cfg_addl_files', array( &$this, 'add_base_files' ), 10, 2 );
|
465 |
+
add_action( 'chld_thm_cfg_addl_files', array( &$this, 'copy_screenshot' ), 10, 2 );
|
466 |
+
add_action( 'chld_thm_cfg_addl_files', array( &$this, 'enqueue_parent_css' ), 15, 2 );
|
467 |
endif;
|
468 |
endif;
|
469 |
// check if we have additional files from a plugin extension. if so, we have to override
|
470 |
// function to support wp_filesystem requirements
|
471 |
+
elseif ( empty( $configtype ) || 'theme' == $configtype ):
|
472 |
// no configtype means this is either from this plugin or a plugin after 1.5.0
|
473 |
+
add_action( 'chld_thm_cfg_addl_files', array( &$this, 'add_base_files' ), 10, 2 );
|
474 |
+
add_action( 'chld_thm_cfg_addl_files', array( &$this, 'copy_screenshot' ), 10, 2 );
|
475 |
+
add_action( 'chld_thm_cfg_addl_files', array( &$this, 'enqueue_parent_css' ), 15, 2 );
|
476 |
+
elseif( has_action( 'chld_thm_cfg_addl_files' ) ):
|
477 |
// action exists so we have to hijack it to use new filesystem checks
|
478 |
remove_all_actions( 'chld_thm_cfg_addl_files' );
|
479 |
// back compat for plugins extension
|
480 |
+
add_action( 'chld_thm_cfg_addl_files', array( &$this, 'write_addl_files' ), 10, 2 );
|
481 |
endif;
|
482 |
|
483 |
+
if ( empty( $name ) ):
|
484 |
+
$name = ucfirst( $child );
|
485 |
endif;
|
486 |
|
487 |
+
if ( empty( $child ) ):
|
488 |
+
$this->errors[] = __( 'Please enter a valid Child Theme directory', 'chld_thm_cfg' );
|
489 |
endif;
|
490 |
|
491 |
+
if ( FALSE === $this->verify_child_dir( $child ) ):
|
492 |
+
$this->errors[] = __( 'Your theme directories are not writable.', 'chld_thm_cfg' );
|
493 |
+
add_action( 'admin_notices', array( $this, 'writable_notice' ) );
|
494 |
endif;
|
495 |
|
496 |
// if no errors so far, we are good to create child theme
|
497 |
+
if ( empty( $this->errors ) ):
|
498 |
$this->css = new ChildThemeConfiguratorCSS();
|
499 |
+
$this->css->set_prop( 'parnt', $parnt );
|
500 |
+
$this->css->set_prop( 'child', $child );
|
501 |
+
$this->css->set_prop( 'child_name', $name );
|
502 |
+
$this->css->set_prop( 'child_author', $author );
|
503 |
+
$this->css->set_prop( 'child_version', strlen( $version ) ? $version : '1.0' );
|
504 |
+
$this->css->set_prop( 'configtype', $configtype );
|
505 |
|
506 |
// hook for add'l plugin files and subdirectories
|
507 |
+
do_action( 'chld_thm_cfg_addl_files', $this );
|
508 |
|
509 |
// always parse parent stylesheet
|
510 |
+
$this->css->parse_css_file( 'parnt' );
|
511 |
|
512 |
+
// parse child stylesheet, backup or skip ( to reset )
|
513 |
+
$this->css->parse_css_file( 'child', $revert );
|
514 |
|
515 |
// parse additional stylesheets
|
516 |
+
if ( isset( $_POST['ctc_additional_css'] ) && is_array( $_POST['ctc_additional_css'] ) ):
|
517 |
$this->css->parentss = array();
|
518 |
+
foreach ( $_POST['ctc_additional_css'] as $file ):
|
519 |
+
$this->css->parse_css_file( 'parnt', $file );
|
520 |
$this->css->parntss[] = $file;
|
521 |
endforeach;
|
522 |
endif;
|
523 |
|
524 |
// try to write new stylsheet. If it fails send alert.
|
525 |
+
if ( FALSE === $this->css->write_css( isset( $_POST['ctc_backup'] ) ) ):
|
526 |
+
$this->errors[] = __( 'Your stylesheet is not writable.', 'chld_thm_cfg' );
|
527 |
+
add_action( 'admin_notices', array( $this, 'writable_notice' ) );
|
528 |
return FALSE;
|
529 |
endif;
|
530 |
|
531 |
// copy parent theme mods option set
|
532 |
+
if ( isset( $_POST['ctc_parent_mods'] ) ):
|
533 |
// we can copy settings from parent to child even if neither is currently active
|
534 |
// so we need cases for active parent, active child or neither
|
535 |
|
536 |
// get active theme
|
537 |
$active_theme = get_stylesheet();
|
538 |
// create temp array from parent settings
|
539 |
+
$child_mods = get_option( 'theme_mods_' . $parnt );
|
540 |
+
if ( $active_theme == $parnt ):
|
541 |
// if parent theme is active, get widgets from active sidebars_widgets array
|
542 |
$child_widgets = retrieve_widgets();
|
543 |
else:
|
544 |
// otherwise get widgets from parent theme mods
|
545 |
$child_widgets = $child_mods['sidebars_widgets']['data'];
|
546 |
endif;
|
547 |
+
if ( $active_theme == $child ):
|
548 |
// if child theme is active, remove widgets from temp array
|
549 |
+
unset( $child_mods['sidebars_widgets'] );
|
550 |
// copy temp array to child mods
|
551 |
+
update_option( 'theme_mods_' . $child, $child_mods );
|
552 |
// copy widgets to active sidebars_widgets array
|
553 |
+
wp_set_sidebars_widgets( $child_widgets );
|
554 |
else:
|
555 |
// otherwise copy widgets to temp array with time stamp
|
556 |
$child_mods['sidebars_widgets']['data'] = $child_widgets;
|
557 |
$child_mods['sidebars_widgets']['time'] = time();
|
558 |
// copy temp array to child theme mods
|
559 |
+
update_option( 'theme_mods_' . $child, $child_mods );
|
560 |
endif;
|
561 |
endif;
|
562 |
|
564 |
$this->css->save_config();
|
565 |
|
566 |
// hook for add'l plugin options
|
567 |
+
do_action( 'chld_thm_cfg_addl_options', $this ); // hook for add'l plugin options
|
568 |
|
569 |
// return message id 1, which says new child theme created successfull;
|
570 |
+
return 1; //isset( $_POST['ctc_scan_subdirs'] ) ? '9&tab=import_options' : 1;
|
571 |
endif;
|
572 |
return FALSE;
|
573 |
}
|
574 |
/*
|
575 |
* TODO: this is a stub for future use
|
576 |
*/
|
577 |
+
function sanitize_options( $input ) {
|
578 |
return $input;
|
579 |
}
|
580 |
|
581 |
+
function update_redirect( $msg = 1 ) {
|
582 |
+
if ( empty( $this->is_ajax ) ):
|
583 |
+
|
584 |
+
wp_safe_redirect(
|
585 |
+
( is_multisite() ?
|
586 |
+
network_admin_url( 'themes.php?page=' . CHLD_THM_CFG_MENU . '&updated=' . $msg ) :
|
587 |
+
admin_url( 'tools.php?page=' . CHLD_THM_CFG_MENU . '&updated=' . $msg ) )
|
588 |
+
);
|
589 |
die();
|
590 |
endif;
|
591 |
}
|
592 |
|
593 |
+
function verify_child_dir( $path ) {
|
594 |
+
if ( !$this->fs ) return FALSE; // return if no filesystem access
|
595 |
global $wp_filesystem;
|
596 |
+
$themedir = $wp_filesystem->find_folder( get_theme_root() );
|
597 |
+
if ( ! $wp_filesystem->is_writable( $themedir ) ) return FALSE;
|
598 |
+
$childparts = explode( '/', $this->normalize_path( $path ) );
|
599 |
+
while ( count( $childparts ) ):
|
600 |
+
$subdir = array_shift( $childparts );
|
601 |
+
if ( empty( $subdir ) ) continue;
|
602 |
+
$themedir = trailingslashit( $themedir ) . $subdir;
|
603 |
+
if ( ! $wp_filesystem->is_dir( $themedir ) ):
|
604 |
+
if ( ! $wp_filesystem->mkdir( $themedir, FS_CHMOD_DIR ) ):
|
605 |
return FALSE;
|
606 |
endif;
|
607 |
+
elseif ( ! $wp_filesystem->is_writable( $themedir ) ):
|
608 |
return FALSE;
|
609 |
endif;
|
610 |
endwhile;
|
611 |
return TRUE;
|
612 |
}
|
613 |
|
614 |
+
function add_base_files( $obj ){
|
615 |
// add functions.php file
|
616 |
$contents = "<?php
|
617 |
// Exit if accessed directly
|
618 |
+
if ( !defined( 'ABSPATH' ) ) exit;
|
619 |
";
|
620 |
+
if ( FALSE === $this->write_child_file( 'functions.php', $contents )
|
621 |
+
|| FALSE === $this->write_child_file( 'style.css', $this->css->get_css_header() ) ) return FALSE;
|
622 |
}
|
623 |
|
624 |
function enqueue_parent_code(){
|
625 |
+
return explode( "\n", apply_filters( 'chld_thm_cfg_enqueue_parent', "
|
626 |
+
if ( !function_exists( 'chld_thm_cfg_parent_css' ) ):
|
627 |
function chld_thm_cfg_parent_css() {
|
628 |
+
wp_enqueue_style( 'chld_thm_cfg_parent', get_template_directory_uri() . '/style.css' );
|
629 |
}
|
630 |
endif;
|
631 |
+
add_action( 'wp_enqueue_scripts', 'chld_thm_cfg_parent_css' );
|
632 |
+
" ) );
|
633 |
}
|
634 |
|
635 |
+
function enqueue_parent_css( $obj ) {
|
636 |
+
if ( isset( $_POST['ctc_parent_enqueue'] ) )
|
637 |
+
$this->css->enqueue = sanitize_text_field( $_POST['ctc_parent_enqueue'] );
|
638 |
$marker = 'ENQUEUE PARENT ACTION';
|
639 |
$insertion = 'enqueue' == $this->css->enqueue ? $this->enqueue_parent_code() : array();
|
640 |
+
if ( $filename = $this->css->is_file_ok( $this->css->get_child_target( 'functions.php' ), 'write' ) ):
|
641 |
$this->insert_with_markers( $filename, $marker, $insertion );
|
642 |
endif;
|
643 |
}
|
647 |
* but it does not use wp_filesystem API!!!???
|
648 |
*/
|
649 |
function insert_with_markers( $filename, $marker, $insertion ) {
|
650 |
+
if ( !$this->fs ) return FALSE; // return if no filesystem access
|
651 |
global $wp_filesystem;
|
652 |
+
if( !$wp_filesystem->exists( $this->fspath( $filename ) ) ):
|
653 |
$markerdata = FALSE;
|
654 |
else:
|
655 |
// get_contents_array returns extra linefeeds so just split it ourself
|
656 |
+
$markerdata = explode( "\n", $wp_filesystem->get_contents( $this->fspath( $filename ) ) );
|
657 |
endif;
|
658 |
$newfile = '';
|
659 |
$foundit = false;
|
660 |
if ( $markerdata ) {
|
661 |
$state = true;
|
662 |
foreach ( $markerdata as $n => $markerline ) {
|
663 |
+
if ( strpos( $markerline, '// BEGIN ' . $marker ) !== false )
|
664 |
$state = false;
|
665 |
if ( $state ):
|
666 |
if ( $n + 1 < count( $markerdata ) )
|
668 |
else
|
669 |
$newfile .= "{$markerline}";
|
670 |
endif;
|
671 |
+
if ( strpos( $markerline, '// END ' . $marker ) !== false ):
|
672 |
$newfile .= "// BEGIN {$marker}\n";
|
673 |
+
if ( is_array( $insertion ) )
|
674 |
foreach ( $insertion as $insertline )
|
675 |
$newfile .= "{$insertline}\n";
|
676 |
$newfile .= "// END {$marker}\n";
|
679 |
endif;
|
680 |
}
|
681 |
}
|
682 |
+
if ( !$foundit ) {
|
683 |
$newfile .= "\n// BEGIN {$marker}\n";
|
684 |
foreach ( $insertion as $insertline )
|
685 |
$newfile .= "{$insertline}\n";
|
686 |
$newfile .= "// END {$marker}\n";
|
687 |
}
|
688 |
+
if ( FALSE === $wp_filesystem->put_contents( $this->fspath( $filename ), $newfile ) ) return FALSE;
|
689 |
}
|
690 |
|
691 |
+
function write_child_file( $file, $contents ) {
|
692 |
+
if ( !$this->fs ) return FALSE; // return if no filesystem access
|
693 |
global $wp_filesystem;
|
694 |
+
$file = $this->fspath( $this->css->is_file_ok( $this->css->get_child_target( $file ), 'write' ) );
|
695 |
+
if ( $file && !$wp_filesystem->exists( $file ) ):
|
696 |
+
if ( FALSE === $wp_filesystem->put_contents( $file, $contents ) ) return FALSE;
|
697 |
endif;
|
698 |
}
|
699 |
|
700 |
+
function copy_screenshot( $obj ) {
|
701 |
// always copy screenshot
|
702 |
+
$this->copy_parent_file( 'screenshot' );
|
703 |
}
|
704 |
|
705 |
+
function copy_parent_file( $file, $ext = 'php' ) {
|
706 |
+
if ( !$this->fs ) return FALSE; // return if no filesystem access
|
707 |
global $wp_filesystem;
|
708 |
$parent_file = NULL;
|
709 |
+
if ( 'screenshot' == $file ):
|
710 |
+
foreach ( array_keys( $this->imgmimes ) as $extreg ):
|
711 |
+
foreach( explode( '|', $extreg ) as $ext ):
|
712 |
+
if ( $parent_file = $this->css->is_file_ok( $this->css->get_parent_source( 'screenshot.' . $ext ) ) ) break;
|
713 |
endforeach;
|
714 |
+
if ( $parent_file ):
|
715 |
+
$parent_file = $this->fspath( $parent_file );
|
716 |
break;
|
717 |
endif;
|
718 |
endforeach;
|
719 |
else:
|
720 |
+
$parent_file = $this->fspath( $this->css->is_file_ok( $this->css->get_parent_source( $file . '.' . $ext ) ) );
|
721 |
endif;
|
722 |
+
// get child theme + file + ext ( passing empty string and full child path to theme_basename )
|
723 |
+
$child_file = $this->css->get_child_target( $file . '.' . $ext );
|
724 |
// return true if file already exists
|
725 |
+
if ( $wp_filesystem->exists( $this->fspath( $child_file ) ) ) return TRUE;
|
726 |
+
$child_dir = dirname( $this->theme_basename( '', $child_file ) );
|
727 |
+
if ( $parent_file // sanity check
|
728 |
&& $child_file // sanity check
|
729 |
+
&& $this->verify_child_dir( $child_dir ) //create child subdir if necessary
|
730 |
+
&& $wp_filesystem->copy( $parent_file, $this->fspath( $child_file ), FS_CHMOD_FILE ) ) return TRUE;
|
731 |
+
$this->errors[] = __( 'Could not copy file.', 'chld_thm_cfg' );
|
732 |
}
|
733 |
|
734 |
+
function delete_child_file( $file, $ext = 'php' ) {
|
735 |
+
if ( !$this->fs ) return FALSE; // return if no filesystem access
|
736 |
global $wp_filesystem;
|
737 |
// verify file is in child theme and exists before removing.
|
738 |
+
$file = ( 'img' == $ext ? $file : $file . '.' . $ext );
|
739 |
+
$child_file = $this->fspath( $this->css->is_file_ok( $this->css->get_child_target( $file ), 'write' ) );
|
740 |
+
if ( $wp_filesystem->exists( $child_file ) ):
|
741 |
+
if ( !$wp_filesystem->delete( $child_file ) ) return FALSE;
|
742 |
endif;
|
743 |
}
|
744 |
|
745 |
+
function get_files( $theme, $type = 'template' ) {
|
746 |
+
if ( !isset( $this->files[$theme] ) ):
|
747 |
$this->files[$theme] = array();
|
748 |
+
$imgext = '(' . implode( '|', array_keys( $this->imgmimes ) ) . ')';
|
749 |
+
foreach ( $this->css->recurse_directory(
|
750 |
+
trailingslashit( get_theme_root() ) . $theme, '', TRUE ) as $file ):
|
751 |
+
$file = $this->theme_basename( $theme, $file );
|
752 |
+
if ( preg_match( "/^style\-(\d+)\.css$/", $file, $matches ) ):
|
753 |
+
$date = date_i18n( 'D, j M Y g:i A', strtotime( $matches[1] ) );
|
754 |
$this->files[$theme]['backup'][$file] = $date;
|
755 |
+
elseif ( preg_match( "/\.php$/", $file ) ):
|
756 |
$this->files[$theme]['template'][] = $file;
|
757 |
+
elseif ( preg_match( "/\.css$/", $file ) && 'style.css' != $file ):
|
758 |
$this->files[$theme]['stylesheet'][] = $file;
|
759 |
+
elseif ( preg_match( "/^images\/.+?\." . $imgext . "$/", $file ) ):
|
760 |
$this->files[$theme]['img'][] = $file;
|
761 |
endif;
|
762 |
endforeach;
|
763 |
endif;
|
764 |
+
return isset( $this->files[$theme][$type] ) ? $this->files[$theme][$type] : array();
|
765 |
}
|
766 |
|
767 |
+
function theme_basename( $theme, $file ) {
|
768 |
// if no theme passed, returns theme + file
|
769 |
+
$themedir = trailingslashit( get_theme_root() ) . ( '' == $theme ? '' : trailingslashit( $theme ) );
|
770 |
+
return preg_replace( '%^' . preg_quote( $themedir ) . '%', '', $file );
|
771 |
}
|
772 |
|
773 |
+
function uploads_basename( $file ) {
|
774 |
+
$file = $this->normalize_path( $file );
|
775 |
$uplarr = wp_upload_dir();
|
776 |
+
$upldir = trailingslashit( $uplarr['basedir'] );
|
777 |
+
return preg_replace( '%^' . preg_quote( $upldir ) . '%', '', $file );
|
778 |
}
|
779 |
|
780 |
+
function uploads_fullpath( $file ) {
|
781 |
+
$file = $this->normalize_path( $file );
|
782 |
$uplarr = wp_upload_dir();
|
783 |
+
$upldir = trailingslashit( $uplarr['basedir'] );
|
784 |
return $upldir . $file;
|
785 |
}
|
786 |
|
787 |
function serialize_postarrays() {
|
788 |
+
foreach ( $this->postarrays as $field )
|
789 |
+
if ( isset( $_POST[$field] ) && is_array( $_POST[$field] ) )
|
790 |
+
$_POST[$field] = implode( "%%", $_POST[$field] );
|
791 |
}
|
792 |
|
793 |
function unserialize_postarrays() {
|
794 |
+
foreach ( $this->postarrays as $field )
|
795 |
+
if ( isset( $_POST[$field] ) && !is_array( $_POST[$field] ) )
|
796 |
+
$_POST[$field] = explode( "%%", $_POST[$field] );
|
797 |
}
|
798 |
|
799 |
+
function set_writable( $file = NULL ) {
|
800 |
|
801 |
+
$file = isset( $file ) ? $this->css->get_child_target( $file . '.php' ) : apply_filters( 'chld_thm_cfg_target', $this->css->get_child_target(), $this->css );
|
802 |
+
if ( $this->fs ): // filesystem access
|
803 |
global $wp_filesystem;
|
804 |
+
if ( $file && $wp_filesystem->chmod( $this->fspath( $file ), 0666 ) ) return;
|
805 |
endif;
|
806 |
+
$this->errors[] = __( 'Could not set write permissions.', 'chld_thm_cfg' );
|
807 |
+
add_action( 'admin_notices', array( $this, 'writable_notice' ) );
|
808 |
return FALSE;
|
809 |
}
|
810 |
|
811 |
function unset_writable() {
|
812 |
+
if ( !$this->fs ) return FALSE; // return if no filesystem access
|
813 |
global $wp_filesystem;
|
814 |
+
$dir = untrailingslashit( $this->css->get_child_target( '' ) );
|
815 |
+
$child = $this->theme_basename( '', $dir );
|
816 |
+
$newchild = untrailingslashit( $child ) . '-new';
|
817 |
+
$themedir = trailingslashit( get_theme_root() );
|
818 |
+
$fsthemedir = $this->fspath( $themedir );
|
819 |
// is child theme owned by user?
|
820 |
+
if ( fileowner( $dir ) == fileowner( ABSPATH ) ):
|
821 |
$copy = FALSE;
|
822 |
+
$wp_filesystem->chmod( $dir );
|
823 |
+
// recursive chmod ( as user )
|
824 |
// WP_Filesystem RECURSIVE CHMOD IS FLAWED! IT SETS ALL CHILDREN TO PERM OF OUTERMOST DIR
|
825 |
+
//if ( $wp_filesystem->chmod( $this->fspath( $dir ), FALSE, TRUE ) ):
|
826 |
//endif;
|
827 |
else:
|
828 |
$copy = TRUE;
|
829 |
endif;
|
830 |
+
// n -> copy entire folder ( as user )
|
831 |
+
$files = $this->css->recurse_directory( $dir, NULL, TRUE );
|
832 |
$errors = array();
|
833 |
+
foreach ( $files as $file ):
|
834 |
+
$childfile = $this->theme_basename( $child, $this->normalize_path( $file ) );
|
835 |
+
$newfile = trailingslashit( $newchild ) . $childfile;
|
836 |
+
$childpath = $fsthemedir . trailingslashit( $child ) . $childfile;
|
837 |
$newpath = $fsthemedir . $newfile;
|
838 |
+
if ( $copy ):
|
839 |
+
if ( $this->verify_child_dir( is_dir( $file ) ? $newfile : dirname( $newfile ) ) ):
|
840 |
+
if ( is_file( $file ) && !$wp_filesystem->copy( $childpath, $newpath ) ):
|
841 |
$errors[] = 'could not copy ' . $newpath;
|
842 |
endif;
|
843 |
else:
|
844 |
$errors[] = 'invalid dir: ' . $newfile;
|
845 |
endif;
|
846 |
else:
|
847 |
+
$wp_filesystem->chmod( $this->fspath( $file ) );
|
848 |
endif;
|
849 |
endforeach;
|
850 |
+
if ( $copy ):
|
851 |
+
// verify copy ( as webserver )
|
852 |
+
$newfiles = $this->css->recurse_directory( trailingslashit( $themedir ) . $newchild, NULL, TRUE );
|
853 |
$deleteddirs = $deletedfiles = 0;
|
854 |
+
if ( count( $newfiles ) == count( $files ) ):
|
855 |
+
// rename old ( as webserver )
|
856 |
+
if ( !$wp_filesystem->exists( trailingslashit( $fsthemedir ) . $child . '-old' ) )
|
857 |
+
$wp_filesystem->move( trailingslashit( $fsthemedir ) . $child, trailingslashit( $fsthemedir ) . $child . '-old' );
|
858 |
+
// rename new ( as user )
|
859 |
+
if ( !$wp_filesystem->exists( trailingslashit( $fsthemedir ) . $child ) )
|
860 |
+
$wp_filesystem->move( trailingslashit( $fsthemedir ) . $newchild, trailingslashit( $fsthemedir ) . $child );
|
861 |
+
// remove old files ( as webserver )
|
862 |
+
$oldfiles = $this->css->recurse_directory( trailingslashit( $themedir ) . $child . '-old', NULL, TRUE );
|
863 |
+
array_unshift( $oldfiles, trailingslashit( $themedir ) . $child . '-old' );
|
864 |
+
foreach ( array_reverse( $oldfiles ) as $file ):
|
865 |
+
if ( $wp_filesystem->delete( $this->fspath( $file ) ) || ( is_dir( $file ) && @rmdir( $file ) ) || ( is_file( $file ) && @unlink( $file ) ) ):
|
866 |
$deletedfiles++;
|
867 |
endif;
|
868 |
endforeach;
|
869 |
+
if ( $deletedfiles != count( $oldfiles ) ):
|
870 |
+
$errors[] = 'deleted: ' . $deletedfiles . ' != ' . count( $oldfiles ) . ' files';
|
871 |
endif;
|
872 |
else:
|
873 |
$errors[] = 'newfiles != files';
|
874 |
endif;
|
875 |
endif;
|
876 |
+
if ( count( $errors ) ):
|
877 |
+
$this->errors[] = __( 'There were errors while resetting permissions.', 'chld_thm_cfg' ) ;
|
878 |
+
add_action( 'admin_notices', array( $this, 'writable_notice' ) );
|
879 |
endif;
|
880 |
}
|
881 |
|
882 |
+
function handle_file_upload( $field, $childdir = NULL, $mimes = NULL ){
|
883 |
$uploadedfile = $_FILES[$field];
|
884 |
$upload_overrides = array(
|
885 |
'test_form' => FALSE,
|
886 |
+
'mimes' => ( is_array( $mimes ) ? $mimes : NULL )
|
887 |
);
|
888 |
if ( ! function_exists( 'wp_handle_upload' ) ) require_once( ABSPATH . 'wp-admin/includes/file.php' );
|
889 |
$movefile = wp_handle_upload( $uploadedfile, $upload_overrides );
|
890 |
+
if ( isset( $movefile['error'] ) ):
|
891 |
$this->errors[] = $movefile['error'];
|
892 |
return FALSE;
|
893 |
endif;
|
894 |
+
$_POST['movefile'] = $this->uploads_basename( $movefile['file'] );
|
895 |
}
|
896 |
|
897 |
+
function move_file_upload( $subdir = 'images' ) {
|
898 |
+
if ( !$this->fs ) return FALSE; // return if no filesystem access
|
899 |
global $wp_filesystem;
|
900 |
+
$source_file = sanitize_text_field( $_POST['movefile'] );
|
901 |
+
$target_file = ( '' == $subdir ?
|
902 |
+
preg_replace( "%^.+(\.\w+)$%", "screenshot$1", basename( $source_file ) ) :
|
903 |
+
trailingslashit( $subdir ) . basename( $source_file ) );
|
904 |
+
if ( FALSE !== $this->verify_child_dir( trailingslashit( $this->css->get_prop( 'child' ) ) . $subdir ) ):
|
905 |
+
$source_path = $this->fspath( $this->uploads_fullpath( $source_file ) );
|
906 |
+
if ( $target_path = $this->css->is_file_ok( $this->css->get_child_target( $target_file ), 'write' ) ):
|
907 |
+
$target_path = $this->fspath( $target_path );
|
908 |
+
if ( $wp_filesystem->exists( $source_path ) ):
|
909 |
+
if ( $wp_filesystem->move( $source_path, $target_path ) ) return TRUE;
|
910 |
endif;
|
911 |
endif;
|
912 |
endif;
|
913 |
|
914 |
+
$this->errors[] = __( 'Could not upload file.', 'chld_thm_cfg' );
|
915 |
}
|
916 |
|
917 |
function export_zip() {
|
918 |
+
if ( ( $child = $this->css->get_prop( 'child' ) )
|
919 |
+
&& ( $dir = $this->css->is_file_ok( dirname( $this->css->get_child_target() ), 'search' ) )
|
920 |
+
&& ( $version = preg_replace( "%[^\w\.\-]%", '', $this->css->get_prop( 'version' ) ) ) ):
|
921 |
// use php system upload dir to store temp files so that we can use pclzip
|
922 |
+
$tmpdir = ini_get( 'upload_tmp_dir' ) ? ini_get( 'upload_tmp_dir' ) : sys_get_temp_dir();
|
923 |
+
$file = trailingslashit( $tmpdir ) . $child . '-' . $version . '.zip';
|
924 |
mbstring_binary_safe_encoding();
|
925 |
|
926 |
+
require_once( ABSPATH . 'wp-admin/includes/class-pclzip.php' );
|
927 |
|
928 |
+
$archive = new PclZip( $file );
|
929 |
+
if ( $archive->create( $dir, PCLZIP_OPT_REMOVE_PATH, dirname( $dir ) ) == 0 ) return FALSE;
|
930 |
reset_mbstring_encoding();
|
931 |
header( 'Content-Description: File Transfer' );
|
932 |
header( 'Content-Type: application/octet-stream' );
|
933 |
+
header( 'Content-Length: ' . filesize( $file ) );
|
934 |
+
header( 'Content-Disposition: attachment; filename=' . basename( $file ) );
|
935 |
+
header( 'Expires: 0' );
|
936 |
+
header( 'Cache-Control: must-revalidate' );
|
937 |
+
header( 'Pragma: public' );
|
938 |
+
readfile( $file );
|
939 |
+
unlink( $file );
|
940 |
die();
|
941 |
endif;
|
942 |
}
|
944 |
/*
|
945 |
*
|
946 |
*/
|
947 |
+
function verify_creds( $args = array() ) {
|
948 |
$this->fs_prompt = $this->fs = FALSE;
|
949 |
//fs prompt does not support arrays as post data - serialize arrays
|
950 |
$this->serialize_postarrays();
|
951 |
// generate callback url
|
952 |
+
$url = is_multisite() ? network_admin_url( 'themes.php?page=' . CHLD_THM_CFG_MENU ) :
|
953 |
+
admin_url( 'tools.php?page=' . CHLD_THM_CFG_MENU );
|
954 |
+
$nonce_url = wp_nonce_url( $url, 'ctc_update', '_wpnonce' );
|
955 |
// buffer output so we can process prior to http header
|
956 |
ob_start();
|
957 |
+
if ( $creds = request_filesystem_credentials( $nonce_url, '', FALSE, FALSE, $args ) ):
|
958 |
// check filesystem permission if direct or ftp creds exist
|
959 |
+
if ( WP_Filesystem( $creds ) )
|
960 |
// login ok
|
961 |
$this->fs = TRUE;
|
962 |
else
|
963 |
// incorrect credentials, get form with error flag
|
964 |
+
$creds = request_filesystem_credentials( $nonce_url, '', TRUE, FALSE, $args );
|
965 |
else:
|
966 |
// no credentials, initialize unpriveledged filesystem object
|
967 |
WP_Filesystem();
|
977 |
/*
|
978 |
* convert 'direct' filepath into wp_filesystem filepath
|
979 |
*/
|
980 |
+
function fspath( $file ){
|
981 |
+
if ( ! $this->fs ) return FALSE; // return if no filesystem access
|
982 |
global $wp_filesystem;
|
983 |
+
if ( is_dir( $file ) ):
|
984 |
$dir = $file;
|
985 |
$base = '';
|
986 |
else:
|
987 |
+
$dir = dirname( $file );
|
988 |
+
$base = basename( $file );
|
989 |
endif;
|
990 |
+
$fsdir = $wp_filesystem->find_folder( $dir );
|
991 |
+
return trailingslashit( $fsdir ) . $base;
|
992 |
}
|
993 |
|
994 |
function writable_notice() {
|
995 |
?> <div class="update-nag">
|
996 |
+
<p><?php _e( 'Child Theme Configurator is unable to write to the stylesheet. This can be resolved using one of the following options:<ol>', 'chld_thm_cfg' );
|
997 |
+
if ( isset( $_SERVER['SERVER_SOFTWARE'] ) && preg_match( '%unix%i',$_SERVER['SERVER_SOFTWARE'] ) ):
|
998 |
+
_e( '<li>Temporarily make the stylesheet writable by clicking the button below. You should change this back when you are finished editing for security by clicking "Make read-only" under the "Files" tab.</li>', 'chld_thm_cfg' );
|
999 |
?><form action="?page=<?php echo CHLD_THM_CFG_MENU; ?>" method="post"><?php wp_nonce_field( 'ctc_update' ); ?>
|
1000 |
+
<input name="ctc_set_writable" class="button" type="submit" value="<?php _e( 'Temporarily make stylesheet writable', 'chld_thm_cfg' ); ?>"/></form><?php endif;
|
1001 |
+
_e( '<li><a target="_blank" href="http://codex.wordpress.org/Editing_wp-config.php#WordPress_Upgrade_Constants" title="Editin wp-config.php">Add your FTP/SSH credentials to the WordPress config file</a>.</li>', 'chld_thm_cfg' );
|
1002 |
+
if ( isset( $_SERVER['SERVER_SOFTWARE'] ) && preg_match( '%iis%i',$_SERVER['SERVER_SOFTWARE'] ) )
|
1003 |
+
_e( '<li><a target="_blank" href="http://technet.microsoft.com/en-us/library/cc771170" title="Setting Application Pool Identity">Assign WordPress to an application pool that has write permissions</a> (Windows IIS systems).</li>', 'chld_thm_cfg' );
|
1004 |
+
_e( '<li><a target="_blank" href="http://codex.wordpress.org/Changing_File_Permissions" title="Changing File Permissions">Set the stylesheet write permissions on the server manually</a> (not recommended).</li>', 'chld_thm_cfg' );
|
1005 |
+
if ( isset( $_SERVER['SERVER_SOFTWARE'] ) && preg_match( '%unix%i',$_SERVER['SERVER_SOFTWARE'] ) )
|
1006 |
+
_e( '<li>Run PHP under Apache with suEXEC (contact your web host).</li>', 'chld_thm_cfg' ) ?>
|
1007 |
</ol></p>
|
1008 |
</div>
|
1009 |
<?php
|
1011 |
function owner_notice() {
|
1012 |
?>
|
1013 |
<div class="update-nag">
|
1014 |
+
<p><?php _e( 'This Child Theme is not owned by your website account. It may have been created by a prior version of this plugin or by another program. Moving forward, it must be owned by your website account to make changes. Child Theme Configurator will attempt to correct this when you click the button below.', 'chld_thm_cfg' ) ?></p>
|
1015 |
<form action="?page=<?php echo CHLD_THM_CFG_MENU; ?>" method="post"><?php wp_nonce_field( 'ctc_update' ); ?>
|
1016 |
+
<input name="ctc_reset_permission" class="button" type="submit" value="<?php _e( 'Correct Child Theme Permissions', 'chld_thm_cfg' ); ?>"/></form> </div>
|
1017 |
<?php
|
1018 |
}
|
1019 |
|
1020 |
function enqueue_notice() {
|
1021 |
?>
|
1022 |
<div class="update-nag">
|
1023 |
+
<p><?php _e( 'Child Theme Configurator has changed the way it handles the parent stylesheet. Please set your preferences below and click "Generate Child Theme Files" to update your configuration.', 'chld_thm_cfg' ) ?></p>
|
1024 |
</div>
|
1025 |
<?php
|
1026 |
}
|
1027 |
|
1028 |
// back compatibility function for plugins extension
|
1029 |
+
function write_addl_files( $chld_thm_cfg ) {
|
1030 |
global $chld_thm_cfg_plugins;
|
1031 |
+
if ( !is_object( $chld_thm_cfg_plugins ) || !$chld_thm_cfg->fs ) return FALSE;
|
1032 |
+
$configtype = $chld_thm_cfg->css->get_prop( 'configtype' );
|
1033 |
+
if ( 'theme' == $configtype || !( $def = $chld_thm_cfg_plugins->defs->get_def( $configtype ) ) ) return FALSE;
|
1034 |
+
$child = trailingslashit( $chld_thm_cfg->css->get_prop( 'child' ) );
|
1035 |
+
if ( isset( $def['addl'] ) && is_array( $def['addl'] ) && count( $def['addl'] ) ):
|
1036 |
+
foreach ( $def['addl'] as $path => $type ):
|
1037 |
|
1038 |
// sanitize the crap out of the target data -- it will be used to create paths
|
1039 |
+
$path = $this->normalize_path( preg_replace( "%[^\w\\//\-]%", '', sanitize_text_field( $child . $path ) ) );
|
1040 |
+
if ( ( 'dir' == $type && FALSE === $chld_thm_cfg->verify_child_dir( $path ) )
|
1041 |
+
|| ( 'dir' != $type && FALSE === $chld_thm_cfg->write_child_file( $path, '' ) ) ):
|
1042 |
$chld_thm_cfg->errors[] =
|
1043 |
+
__( 'Your theme directories are not writable.', 'chld_thm_cfg_plugins' );
|
1044 |
endif;
|
1045 |
endforeach;
|
1046 |
endif;
|
1047 |
// write main def file
|
1048 |
+
if ( isset( $def['target'] ) ):
|
1049 |
+
$path = $this->normalize_path( preg_replace( "%[^\w\\//\-\.]%", '', sanitize_text_field( $def['target'] ) ) ); //$child .
|
1050 |
+
if ( FALSE === $chld_thm_cfg->write_child_file( $path, '' ) ):
|
1051 |
$chld_thm_cfg->errors[] =
|
1052 |
+
__( 'Your stylesheet is not writable.', 'chld_thm_cfg_plugins' );
|
1053 |
return FALSE;
|
1054 |
endif;
|
1055 |
endif;
|
includes/forms/at-import.php
CHANGED
@@ -1,5 +1,5 @@
|
|
1 |
<?php
|
2 |
-
if (!defined('ABSPATH')) exit;
|
3 |
// @imports Panel
|
4 |
?>
|
5 |
|
@@ -11,17 +11,17 @@ if (!defined('ABSPATH')) exit;
|
|
11 |
<div class="ctc-input-cell">
|
12 |
<div class="ctc-textarea-button-cell" id="ctc_save_imports_cell">
|
13 |
<input type="button" class="button ctc-save-input" id="ctc_save_imports"
|
14 |
-
name="ctc_save_imports" value="<?php _e('Save', 'chld_thm_cfg'); ?>" disabled />
|
15 |
</div>
|
16 |
<strong>
|
17 |
-
<?php _e('@import Statements', 'chld_thm_cfg'); ?>
|
18 |
</strong>
|
19 |
</div>
|
20 |
<div class="ctc-input-cell-wide">
|
21 |
<textarea id="ctc_child_imports" name="ctc_child_imports" wrap="off"><?php
|
22 |
-
if (!empty($imports)):
|
23 |
-
foreach ($imports as $import):
|
24 |
-
echo esc_textarea($import . ';' . LF);
|
25 |
endforeach;
|
26 |
endif; ?>
|
27 |
</textarea>
|
1 |
<?php
|
2 |
+
if ( !defined( 'ABSPATH' ) ) exit;
|
3 |
// @imports Panel
|
4 |
?>
|
5 |
|
11 |
<div class="ctc-input-cell">
|
12 |
<div class="ctc-textarea-button-cell" id="ctc_save_imports_cell">
|
13 |
<input type="button" class="button ctc-save-input" id="ctc_save_imports"
|
14 |
+
name="ctc_save_imports" value="<?php _e( 'Save', 'chld_thm_cfg' ); ?>" disabled />
|
15 |
</div>
|
16 |
<strong>
|
17 |
+
<?php _e( '@import Statements', 'chld_thm_cfg' ); ?>
|
18 |
</strong>
|
19 |
</div>
|
20 |
<div class="ctc-input-cell-wide">
|
21 |
<textarea id="ctc_child_imports" name="ctc_child_imports" wrap="off"><?php
|
22 |
+
if ( !empty( $imports ) ):
|
23 |
+
foreach ( $imports as $import ):
|
24 |
+
echo esc_textarea( $import . ';' . LF );
|
25 |
endforeach;
|
26 |
endif; ?>
|
27 |
</textarea>
|
includes/forms/backup.php
CHANGED
@@ -1,8 +1,8 @@
|
|
1 |
<?php
|
2 |
-
if (!defined('ABSPATH')) exit;
|
3 |
// Backup Input Cell
|
4 |
?>
|
5 |
-
<label class="ctc-input-cell smaller<?php echo 'child' == $template && !$this->ctc()->fs && is_writable($themeroot . $backup) ? ' writable' : ''; ?>">
|
6 |
<input class="ctc_checkbox" id="ctc_file_<?php echo $template . '_' . ++$counter; ?>"
|
7 |
name="ctc_file_<?php echo $template; ?>[]" type="checkbox"
|
8 |
-
value="<?php echo $templatefile; ?>" /><?php echo __('Backup', 'chld_thm_cfg') . ' ' . $label; ?></label>
|
1 |
<?php
|
2 |
+
if ( !defined( 'ABSPATH' ) ) exit;
|
3 |
// Backup Input Cell
|
4 |
?>
|
5 |
+
<label class="ctc-input-cell smaller<?php echo 'child' == $template && !$this->ctc()->fs && is_writable( $themeroot . $backup ) ? ' writable' : ''; ?>">
|
6 |
<input class="ctc_checkbox" id="ctc_file_<?php echo $template . '_' . ++$counter; ?>"
|
7 |
name="ctc_file_<?php echo $template; ?>[]" type="checkbox"
|
8 |
+
value="<?php echo $templatefile; ?>" /><?php echo __( 'Backup', 'chld_thm_cfg' ) . ' ' . $label; ?></label>
|
includes/forms/file.php
CHANGED
@@ -1,8 +1,8 @@
|
|
1 |
<?php
|
2 |
-
if (!defined('ABSPATH')) exit;
|
3 |
// File Input Cell
|
4 |
?>
|
5 |
-
<label class="ctc-input-cell smaller<?php echo 'child' == $template && !$this->ctc()->fs && is_writable($themeroot . $file) ? ' writable' : ''; ?>">
|
6 |
<input class="ctc_checkbox" id="ctc_file_<?php echo $template . '_' . ++$counter; ?>"
|
7 |
name="ctc_file_<?php echo $template; ?>[]" type="checkbox"
|
8 |
value="<?php echo $templatefile; ?>" />
|
1 |
<?php
|
2 |
+
if ( !defined( 'ABSPATH' ) ) exit;
|
3 |
// File Input Cell
|
4 |
?>
|
5 |
+
<label class="ctc-input-cell smaller<?php echo 'child' == $template && !$this->ctc()->fs && is_writable( $themeroot . $file ) ? ' writable' : ''; ?>">
|
6 |
<input class="ctc_checkbox" id="ctc_file_<?php echo $template . '_' . ++$counter; ?>"
|
7 |
name="ctc_file_<?php echo $template; ?>[]" type="checkbox"
|
8 |
value="<?php echo $templatefile; ?>" />
|
includes/forms/fileform.php
CHANGED
@@ -1,16 +1,17 @@
|
|
1 |
<?php
|
2 |
-
if (!defined('ABSPATH')) exit;
|
3 |
// Files Section
|
4 |
// This include is used for both parent template section and the child files section
|
5 |
|
6 |
-
if (defined('DISALLOW_FILE_EDIT') && DISALLOW_FILE_EDIT):
|
7 |
-
$linktext = __('The Theme editor has been disabled. Template files must be edited offline.', 'chld_thm_cfg');
|
8 |
$editorlink = '';
|
9 |
$editorlinkend = '';
|
10 |
else:
|
11 |
-
$linktext = __('Click here to edit template files using the Theme Editor', 'chld_thm_cfg');
|
12 |
-
$
|
13 |
-
. ('parnt' == $template ? '&file=functions.php' : '')
|
|
|
14 |
$editorlinkend = '</a>';
|
15 |
endif;
|
16 |
?>
|
@@ -18,17 +19,17 @@ endif;
|
|
18 |
<form id="ctc_<?php echo $template; ?>_templates_form" method="post" action="?page=<?php echo CHLD_THM_CFG_MENU; ?>&tab=file_options">
|
19 |
<?php wp_nonce_field( 'ctc_update' ); ?>
|
20 |
<div class="ctc-input-cell"> <strong>
|
21 |
-
<?php echo 'parnt' == $template ? __('Parent Templates', 'chld_thm_cfg') : __('Child Theme Files', 'chld_thm_cfg'); ?>
|
22 |
</strong>
|
23 |
<?php
|
24 |
-
if ('parnt' == $template): ?>
|
25 |
<p class="howto">
|
26 |
-
<?php _e('Copy PHP template files from the parent theme by selecting them here.', 'chld_thm_cfg'); ?>
|
27 |
</p>
|
28 |
<p><strong>
|
29 |
-
<?php _e('CAUTION: If your child theme is active, the child theme version of the file will be used instead of the parent immediately after it is copied.', 'chld_thm_cfg');?>
|
30 |
</strong></p>
|
31 |
-
<p class="howto"> <?php echo sprintf(__('The %s file is generated separately and cannot be copied here.', 'chld_thm_cfg'),
|
32 |
$editorlink . '<code>functions.php</code>' . $editorlinkend
|
33 |
);
|
34 |
else: ?>
|
@@ -37,8 +38,8 @@ else: ?>
|
|
37 |
</p>
|
38 |
<p class="howto">
|
39 |
<?php
|
40 |
-
echo ($this->ctc()->fs ?
|
41 |
-
__( 'Delete child theme templates by selecting them here.', 'chld_thm_cfg') :
|
42 |
__( 'Delete child theme templates or make them writable by selecting them here. Writable files are displayed in <span style="color:red">red</span>.', 'chld_thm_cfg' )
|
43 |
); ?>
|
44 |
</p>
|
@@ -49,14 +50,14 @@ else: ?>
|
|
49 |
<div class="ctc-input-cell-wide"> <?php echo $inputs; ?></div>
|
50 |
<div class="ctc-input-cell"> <strong> </strong> </div>
|
51 |
<div class="ctc-input-cell-wide" style="margin-top:10px;margin-bottom:10px">
|
52 |
-
<?php if ('child' == $template && !$this->ctc()->fs): ?>
|
53 |
<input class="ctc_submit button button-primary" id="ctc_templates_writable_submit"
|
54 |
name="ctc_templates_writable_submit" type="submit"
|
55 |
-
value="<?php _e('Make Selected Writable', 'chld_thm_cfg'); ?>" />
|
56 |
<?php endif; ?>
|
57 |
<input class="ctc_submit button button-primary" id="ctc_<?php echo $template; ?>_templates_submit"
|
58 |
name="ctc_<?php echo $template; ?>_templates_submit" type="submit"
|
59 |
-
value="<?php echo ('parnt' == $template ? __('Copy Selected to Child Theme', 'chld_thm_cfg') : __('Delete Selected', 'chld_thm_cfg')); ?>" />
|
60 |
</div>
|
61 |
</form>
|
62 |
</div>
|
1 |
<?php
|
2 |
+
if ( !defined( 'ABSPATH' ) ) exit;
|
3 |
// Files Section
|
4 |
// This include is used for both parent template section and the child files section
|
5 |
|
6 |
+
if ( defined( 'DISALLOW_FILE_EDIT' ) && DISALLOW_FILE_EDIT ):
|
7 |
+
$linktext = __( 'The Theme editor has been disabled. Template files must be edited offline.', 'chld_thm_cfg' );
|
8 |
$editorlink = '';
|
9 |
$editorlinkend = '';
|
10 |
else:
|
11 |
+
$linktext = __( 'Click here to edit template files using the Theme Editor', 'chld_thm_cfg' );
|
12 |
+
$adminbase = 'theme-editor.php?theme=' . $this->ctc()->css->get_prop( 'child' )
|
13 |
+
. ( 'parnt' == $template ? '&file=functions.php' : '' );
|
14 |
+
$editorlink = '<a href="' . ( is_multisite() ? network_admin_url( $adminbase ) : admin_url( $adminbase ) ) . '" title="' . $linktext . '">';
|
15 |
$editorlinkend = '</a>';
|
16 |
endif;
|
17 |
?>
|
19 |
<form id="ctc_<?php echo $template; ?>_templates_form" method="post" action="?page=<?php echo CHLD_THM_CFG_MENU; ?>&tab=file_options">
|
20 |
<?php wp_nonce_field( 'ctc_update' ); ?>
|
21 |
<div class="ctc-input-cell"> <strong>
|
22 |
+
<?php echo 'parnt' == $template ? __( 'Parent Templates', 'chld_thm_cfg' ) : __( 'Child Theme Files', 'chld_thm_cfg' ); ?>
|
23 |
</strong>
|
24 |
<?php
|
25 |
+
if ( 'parnt' == $template ): ?>
|
26 |
<p class="howto">
|
27 |
+
<?php _e( 'Copy PHP template files from the parent theme by selecting them here.', 'chld_thm_cfg' ); ?>
|
28 |
</p>
|
29 |
<p><strong>
|
30 |
+
<?php _e( 'CAUTION: If your child theme is active, the child theme version of the file will be used instead of the parent immediately after it is copied.', 'chld_thm_cfg' );?>
|
31 |
</strong></p>
|
32 |
+
<p class="howto"> <?php echo sprintf( __( 'The %s file is generated separately and cannot be copied here.', 'chld_thm_cfg' ),
|
33 |
$editorlink . '<code>functions.php</code>' . $editorlinkend
|
34 |
);
|
35 |
else: ?>
|
38 |
</p>
|
39 |
<p class="howto">
|
40 |
<?php
|
41 |
+
echo ( $this->ctc()->fs ?
|
42 |
+
__( 'Delete child theme templates by selecting them here.', 'chld_thm_cfg' ) :
|
43 |
__( 'Delete child theme templates or make them writable by selecting them here. Writable files are displayed in <span style="color:red">red</span>.', 'chld_thm_cfg' )
|
44 |
); ?>
|
45 |
</p>
|
50 |
<div class="ctc-input-cell-wide"> <?php echo $inputs; ?></div>
|
51 |
<div class="ctc-input-cell"> <strong> </strong> </div>
|
52 |
<div class="ctc-input-cell-wide" style="margin-top:10px;margin-bottom:10px">
|
53 |
+
<?php if ( 'child' == $template && !$this->ctc()->fs ): ?>
|
54 |
<input class="ctc_submit button button-primary" id="ctc_templates_writable_submit"
|
55 |
name="ctc_templates_writable_submit" type="submit"
|
56 |
+
value="<?php _e( 'Make Selected Writable', 'chld_thm_cfg' ); ?>" />
|
57 |
<?php endif; ?>
|
58 |
<input class="ctc_submit button button-primary" id="ctc_<?php echo $template; ?>_templates_submit"
|
59 |
name="ctc_<?php echo $template; ?>_templates_submit" type="submit"
|
60 |
+
value="<?php echo ( 'parnt' == $template ? __( 'Copy Selected to Child Theme', 'chld_thm_cfg' ) : __( 'Delete Selected', 'chld_thm_cfg' ) ); ?>" />
|
61 |
</div>
|
62 |
</form>
|
63 |
</div>
|
includes/forms/files.php
CHANGED
@@ -1,35 +1,35 @@
|
|
1 |
<?php
|
2 |
-
if (!defined('ABSPATH')) exit;
|
3 |
// Files Panel
|
4 |
?>
|
5 |
|
6 |
<div id="file_options_panel"
|
7 |
class="ctc-option-panel<?php echo 'file_options' == $active_tab ? ' ctc-option-panel-active' : ''; ?>" <?php echo $hidechild; ?>>
|
8 |
-
<?php $this->render_file_form('parnt'); ?>
|
9 |
-
<?php $this->render_file_form('child'); ?>
|
10 |
<?php $this->render_image_form(); ?>
|
11 |
<div class="ctc-input-row clearfix" id="input_row_theme_image">
|
12 |
<form id="ctc_theme_image_form" method="post" action="?page=<?php echo CHLD_THM_CFG_MENU; ?>" enctype="multipart/form-data">
|
13 |
<?php wp_nonce_field( 'ctc_update' ); ?>
|
14 |
<div class="ctc-input-cell"> <strong>
|
15 |
-
<?php _e('Upload New Child Theme Image', 'chld_thm_cfg'); ?>
|
16 |
</strong>
|
17 |
<p class="howto">
|
18 |
-
<?php _e('Theme images reside under the <code>images</code> directory in your child theme and are meant for stylesheet use only. Use the Media Library for content images.', 'chld_thm_cfg'); ?>
|
19 |
</p>
|
20 |
</div>
|
21 |
<div class="ctc-input-cell-wide">
|
22 |
<input type="file" id="ctc_theme_image" name="ctc_theme_image" value="" />
|
23 |
<input class="ctc_submit button button-primary" id="ctc_theme_image_submit"
|
24 |
name="ctc_theme_image_submit" type="submit"
|
25 |
-
value="<?php _e('Upload', 'chld_thm_cfg'); ?>" />
|
26 |
</div>
|
27 |
</form>
|
28 |
</div>
|
29 |
-
<?php if ($screenshot = $this->get_theme_screenshot()): ?>
|
30 |
<div class="ctc-input-row clearfix" id="input_row_screenshot_view">
|
31 |
<div class="ctc-input-cell"> <strong>
|
32 |
-
<?php _e('Child Theme Screenshot', 'chld_thm_cfg'); ?>
|
33 |
</strong> </div>
|
34 |
<div class="ctc-input-cell-wide"> <a href="<?php echo $screenshot; ?>" class="thickbox"><img src="<?php echo $screenshot; ?>" height="150" width="200" style="max-height:150px;max-width:200px;width:auto;height:auto" /></a> </div>
|
35 |
</div>
|
@@ -38,17 +38,17 @@ if (!defined('ABSPATH')) exit;
|
|
38 |
<form id="ctc_screenshot_form" method="post" action="?page=<?php echo CHLD_THM_CFG_MENU; ?>" enctype="multipart/form-data">
|
39 |
<?php wp_nonce_field( 'ctc_update' ); ?>
|
40 |
<div class="ctc-input-cell"> <strong>
|
41 |
-
<?php _e('Upload New Screenshot', 'chld_thm_cfg'); ?>
|
42 |
</strong>
|
43 |
<p class="howto">
|
44 |
-
<?php _e('The theme screenshot should be a 4:3 ratio (e.g., 880px x 660px) JPG, PNG or GIF. It will be renamed <code>screenshot</code>.', 'chld_thm_cfg'); ?>
|
45 |
</p>
|
46 |
</div>
|
47 |
<div class="ctc-input-cell-wide">
|
48 |
<input type="file" id="ctc_theme_screenshot" name="ctc_theme_screenshot" value="" />
|
49 |
<input class="ctc_submit button button-primary" id="ctc_theme_screenshot_submit"
|
50 |
name="ctc_theme_screenshot_submit" type="submit"
|
51 |
-
value="<?php _e('Upload', 'chld_thm_cfg'); ?>" />
|
52 |
</div>
|
53 |
</form>
|
54 |
</div>
|
@@ -56,30 +56,30 @@ if (!defined('ABSPATH')) exit;
|
|
56 |
<form id="ctc_export_form" method="post" action="?page=<?php echo CHLD_THM_CFG_MENU; ?>">
|
57 |
<?php wp_nonce_field( 'ctc_update' ); ?>
|
58 |
<div class="ctc-input-cell"> <strong>
|
59 |
-
<?php _e('Export Child Theme as Zip Archive', 'chld_thm_cfg'); ?>
|
60 |
</strong> </div>
|
61 |
<div class="ctc-input-cell-wide">
|
62 |
<input class="ctc_submit button button-primary" id="ctc_export_child_zip"
|
63 |
name="ctc_export_child_zip" type="submit"
|
64 |
-
value="<?php _e('Export', 'chld_thm_cfg'); ?>" />
|
65 |
</div>
|
66 |
</form>
|
67 |
</div>
|
68 |
-
<?php if ('direct' != $this->ctc()->fs_method): ?>
|
69 |
<div class="ctc-input-row clearfix" id="input_row_permissions">
|
70 |
<form id="ctc_permission_form" method="post" action="?page=<?php echo CHLD_THM_CFG_MENU; ?>">
|
71 |
<?php wp_nonce_field( 'ctc_update' ); ?>
|
72 |
<div class="ctc-input-cell"> <strong>
|
73 |
-
<?php _e('Secure Child Theme', 'chld_thm_cfg'); ?>
|
74 |
</strong>
|
75 |
<p class="howto">
|
76 |
-
<?php _e('Attempt to reset child theme permissions to user ownership and read-only access.', 'chld_thm_cfg'); ?>
|
77 |
</p>
|
78 |
</div>
|
79 |
<div class="ctc-input-cell-wide">
|
80 |
<input class="ctc_submit button button-primary" id="ctc_reset_permission"
|
81 |
name="ctc_reset_permission" type="submit"
|
82 |
-
value="<?php _e('Make read-only', 'chld_thm_cfg'); ?>" />
|
83 |
</div>
|
84 |
</form>
|
85 |
</div>
|
1 |
<?php
|
2 |
+
if ( !defined( 'ABSPATH' ) ) exit;
|
3 |
// Files Panel
|
4 |
?>
|
5 |
|
6 |
<div id="file_options_panel"
|
7 |
class="ctc-option-panel<?php echo 'file_options' == $active_tab ? ' ctc-option-panel-active' : ''; ?>" <?php echo $hidechild; ?>>
|
8 |
+
<?php $this->render_file_form( 'parnt' ); ?>
|
9 |
+
<?php $this->render_file_form( 'child' ); ?>
|
10 |
<?php $this->render_image_form(); ?>
|
11 |
<div class="ctc-input-row clearfix" id="input_row_theme_image">
|
12 |
<form id="ctc_theme_image_form" method="post" action="?page=<?php echo CHLD_THM_CFG_MENU; ?>" enctype="multipart/form-data">
|
13 |
<?php wp_nonce_field( 'ctc_update' ); ?>
|
14 |
<div class="ctc-input-cell"> <strong>
|
15 |
+
<?php _e( 'Upload New Child Theme Image', 'chld_thm_cfg' ); ?>
|
16 |
</strong>
|
17 |
<p class="howto">
|
18 |
+
<?php _e( 'Theme images reside under the <code>images</code> directory in your child theme and are meant for stylesheet use only. Use the Media Library for content images.', 'chld_thm_cfg' ); ?>
|
19 |
</p>
|
20 |
</div>
|
21 |
<div class="ctc-input-cell-wide">
|
22 |
<input type="file" id="ctc_theme_image" name="ctc_theme_image" value="" />
|
23 |
<input class="ctc_submit button button-primary" id="ctc_theme_image_submit"
|
24 |
name="ctc_theme_image_submit" type="submit"
|
25 |
+
value="<?php _e( 'Upload', 'chld_thm_cfg' ); ?>" />
|
26 |
</div>
|
27 |
</form>
|
28 |
</div>
|
29 |
+
<?php if ( $screenshot = $this->get_theme_screenshot() ): ?>
|
30 |
<div class="ctc-input-row clearfix" id="input_row_screenshot_view">
|
31 |
<div class="ctc-input-cell"> <strong>
|
32 |
+
<?php _e( 'Child Theme Screenshot', 'chld_thm_cfg' ); ?>
|
33 |
</strong> </div>
|
34 |
<div class="ctc-input-cell-wide"> <a href="<?php echo $screenshot; ?>" class="thickbox"><img src="<?php echo $screenshot; ?>" height="150" width="200" style="max-height:150px;max-width:200px;width:auto;height:auto" /></a> </div>
|
35 |
</div>
|
38 |
<form id="ctc_screenshot_form" method="post" action="?page=<?php echo CHLD_THM_CFG_MENU; ?>" enctype="multipart/form-data">
|
39 |
<?php wp_nonce_field( 'ctc_update' ); ?>
|
40 |
<div class="ctc-input-cell"> <strong>
|
41 |
+
<?php _e( 'Upload New Screenshot', 'chld_thm_cfg' ); ?>
|
42 |
</strong>
|
43 |
<p class="howto">
|
44 |
+
<?php _e( 'The theme screenshot should be a 4:3 ratio (e.g., 880px x 660px) JPG, PNG or GIF. It will be renamed <code>screenshot</code>.', 'chld_thm_cfg' ); ?>
|
45 |
</p>
|
46 |
</div>
|
47 |
<div class="ctc-input-cell-wide">
|
48 |
<input type="file" id="ctc_theme_screenshot" name="ctc_theme_screenshot" value="" />
|
49 |
<input class="ctc_submit button button-primary" id="ctc_theme_screenshot_submit"
|
50 |
name="ctc_theme_screenshot_submit" type="submit"
|
51 |
+
value="<?php _e( 'Upload', 'chld_thm_cfg' ); ?>" />
|
52 |
</div>
|
53 |
</form>
|
54 |
</div>
|
56 |
<form id="ctc_export_form" method="post" action="?page=<?php echo CHLD_THM_CFG_MENU; ?>">
|
57 |
<?php wp_nonce_field( 'ctc_update' ); ?>
|
58 |
<div class="ctc-input-cell"> <strong>
|
59 |
+
<?php _e( 'Export Child Theme as Zip Archive', 'chld_thm_cfg' ); ?>
|
60 |
</strong> </div>
|
61 |
<div class="ctc-input-cell-wide">
|
62 |
<input class="ctc_submit button button-primary" id="ctc_export_child_zip"
|
63 |
name="ctc_export_child_zip" type="submit"
|
64 |
+
value="<?php _e( 'Export', 'chld_thm_cfg' ); ?>" />
|
65 |
</div>
|
66 |
</form>
|
67 |
</div>
|
68 |
+
<?php if ( 'direct' != $this->ctc()->fs_method ): ?>
|
69 |
<div class="ctc-input-row clearfix" id="input_row_permissions">
|
70 |
<form id="ctc_permission_form" method="post" action="?page=<?php echo CHLD_THM_CFG_MENU; ?>">
|
71 |
<?php wp_nonce_field( 'ctc_update' ); ?>
|
72 |
<div class="ctc-input-cell"> <strong>
|
73 |
+
<?php _e( 'Secure Child Theme', 'chld_thm_cfg' ); ?>
|
74 |
</strong>
|
75 |
<p class="howto">
|
76 |
+
<?php _e( 'Attempt to reset child theme permissions to user ownership and read-only access.', 'chld_thm_cfg' ); ?>
|
77 |
</p>
|
78 |
</div>
|
79 |
<div class="ctc-input-cell-wide">
|
80 |
<input class="ctc_submit button button-primary" id="ctc_reset_permission"
|
81 |
name="ctc_reset_permission" type="submit"
|
82 |
+
value="<?php _e( 'Make read-only', 'chld_thm_cfg' ); ?>" />
|
83 |
</div>
|
84 |
</form>
|
85 |
</div>
|
includes/forms/image.php
CHANGED
@@ -1,5 +1,5 @@
|
|
1 |
<?php
|
2 |
-
if (!defined('ABSPATH')) exit;
|
3 |
// Image Input Cell
|
4 |
?>
|
5 |
<div class="ctc-input-cell" style="height:100px">
|
1 |
<?php
|
2 |
+
if ( !defined( 'ABSPATH' ) ) exit;
|
3 |
// Image Input Cell
|
4 |
?>
|
5 |
<div class="ctc-input-cell" style="height:100px">
|
includes/forms/images.php
CHANGED
@@ -1,15 +1,15 @@
|
|
1 |
<?php
|
2 |
-
if (!defined('ABSPATH')) exit;
|
3 |
// Images Section
|
4 |
?>
|
5 |
<div class="ctc-input-row clearfix" id="input_row_images">
|
6 |
<form id="ctc_image_form" method="post" action="?page=<?php echo CHLD_THM_CFG_MENU; ?>">
|
7 |
<?php wp_nonce_field( 'ctc_update' ); ?>
|
8 |
<div class="ctc-input-cell"> <strong>
|
9 |
-
<?php _e('Child Theme Images', 'chld_thm_cfg'); ?>
|
10 |
</strong>
|
11 |
<p class="howto">
|
12 |
-
<?php _e('Delete child theme images by selecting them here.', 'chld_thm_cfg');?>
|
13 |
</p>
|
14 |
</div>
|
15 |
<div class="ctc-input-cell-wide"> <?php echo $inputs; ?> </div>
|
@@ -17,7 +17,7 @@ if (!defined('ABSPATH')) exit;
|
|
17 |
<div class="ctc-input-cell-wide" style="margin-top:10px;margin-bottom:10px">
|
18 |
<input class="ctc_submit button button-primary" id="ctc_image_submit"
|
19 |
name="ctc_image_submit" type="submit"
|
20 |
-
value="<?php _e('Delete Selected', 'chld_thm_cfg'); ?>" disabled />
|
21 |
</div>
|
22 |
</form>
|
23 |
</div>
|
1 |
<?php
|
2 |
+
if ( !defined( 'ABSPATH' ) ) exit;
|
3 |
// Images Section
|
4 |
?>
|
5 |
<div class="ctc-input-row clearfix" id="input_row_images">
|
6 |
<form id="ctc_image_form" method="post" action="?page=<?php echo CHLD_THM_CFG_MENU; ?>">
|
7 |
<?php wp_nonce_field( 'ctc_update' ); ?>
|
8 |
<div class="ctc-input-cell"> <strong>
|
9 |
+
<?php _e( 'Child Theme Images', 'chld_thm_cfg' ); ?>
|
10 |
</strong>
|
11 |
<p class="howto">
|
12 |
+
<?php _e( 'Delete child theme images by selecting them here.', 'chld_thm_cfg' );?>
|
13 |
</p>
|
14 |
</div>
|
15 |
<div class="ctc-input-cell-wide"> <?php echo $inputs; ?> </div>
|
17 |
<div class="ctc-input-cell-wide" style="margin-top:10px;margin-bottom:10px">
|
18 |
<input class="ctc_submit button button-primary" id="ctc_image_submit"
|
19 |
name="ctc_image_submit" type="submit"
|
20 |
+
value="<?php _e( 'Delete Selected', 'chld_thm_cfg' ); ?>" disabled />
|
21 |
</div>
|
22 |
</form>
|
23 |
</div>
|
includes/forms/main.php
CHANGED
@@ -1,5 +1,5 @@
|
|
1 |
<?php
|
2 |
-
if (!defined('ABSPATH')) exit;
|
3 |
// main CTC Page
|
4 |
?>
|
5 |
<style type="text/css">
|
@@ -9,20 +9,20 @@ if (!defined('ABSPATH')) exit;
|
|
9 |
}
|
10 |
|
11 |
.ctc-status-icon.failure {
|
12 |
-
background:url(<?php echo admin_url( 'images/no.png');
|
13 |
?>) no-repeat;
|
14 |
}
|
15 |
|
16 |
.ctc-exit {
|
17 |
-
background:#f9f9f9 url(<?php echo includes_url('images/xit-2x.gif');
|
18 |
?>) left top no-repeat;
|
19 |
}
|
20 |
</style>
|
21 |
<div class="wrap">
|
22 |
-
<?php do_action('chld_thm_cfg_related_links'); ?>
|
23 |
-
<h2><?php echo __('Child Theme Configurator', 'chld_thm_cfg') . ' ' . __('version', 'chld_thm_cfg') . ' ' . CHLD_THM_CFG_VERSION; ?></h2>
|
24 |
<?php
|
25 |
-
if ('POST' == $_SERVER['REQUEST_METHOD'] && !$this->ctc()->fs):
|
26 |
echo $this->ctc()->fs_prompt;
|
27 |
else: ?>
|
28 |
<div id="ctc_error_notice">
|
@@ -36,7 +36,7 @@ else: ?>
|
|
36 |
<div class="ctc-option-panel-container">
|
37 |
<?php
|
38 |
include ( $this->ctc()->pluginPath . 'includes/forms/parent-child.php' );
|
39 |
-
if ($enqueueset):
|
40 |
include ( $this->ctc()->pluginPath . 'includes/forms/rule-value.php' );
|
41 |
include ( $this->ctc()->pluginPath . 'includes/forms/query-selector.php' );
|
42 |
include ( $this->ctc()->pluginPath . 'includes/forms/at-import.php' ); ?>
|
@@ -45,10 +45,10 @@ else: ?>
|
|
45 |
<div id="view_parnt_options_panel"
|
46 |
class="ctc-option-panel<?php echo 'view_parnt_options' == $active_tab ? ' ctc-option-panel-active' : ''; ?>" <?php echo $hidechild; ?>> </div>
|
47 |
<?php
|
48 |
-
if ('' == $hidechild):
|
49 |
include ( $this->ctc()->pluginPath . 'includes/forms/files.php' );
|
50 |
endif;
|
51 |
-
do_action('chld_thm_cfg_panels', $this->ctc(), $active_tab, $hidechild);
|
52 |
endif; ?>
|
53 |
</div>
|
54 |
<?php
|
1 |
<?php
|
2 |
+
if ( !defined( 'ABSPATH' ) ) exit;
|
3 |
// main CTC Page
|
4 |
?>
|
5 |
<style type="text/css">
|
9 |
}
|
10 |
|
11 |
.ctc-status-icon.failure {
|
12 |
+
background:url(<?php echo admin_url( 'images/no.png' );
|
13 |
?>) no-repeat;
|
14 |
}
|
15 |
|
16 |
.ctc-exit {
|
17 |
+
background:#f9f9f9 url(<?php echo includes_url( 'images/xit-2x.gif' );
|
18 |
?>) left top no-repeat;
|
19 |
}
|
20 |
</style>
|
21 |
<div class="wrap">
|
22 |
+
<?php do_action( 'chld_thm_cfg_related_links' ); ?>
|
23 |
+
<h2><?php echo __( 'Child Theme Configurator', 'chld_thm_cfg' ) . ' ' . __( 'version', 'chld_thm_cfg' ) . ' ' . CHLD_THM_CFG_VERSION; ?></h2>
|
24 |
<?php
|
25 |
+
if ( 'POST' == $_SERVER['REQUEST_METHOD'] && !$this->ctc()->fs ):
|
26 |
echo $this->ctc()->fs_prompt;
|
27 |
else: ?>
|
28 |
<div id="ctc_error_notice">
|
36 |
<div class="ctc-option-panel-container">
|
37 |
<?php
|
38 |
include ( $this->ctc()->pluginPath . 'includes/forms/parent-child.php' );
|
39 |
+
if ( $enqueueset ):
|
40 |
include ( $this->ctc()->pluginPath . 'includes/forms/rule-value.php' );
|
41 |
include ( $this->ctc()->pluginPath . 'includes/forms/query-selector.php' );
|
42 |
include ( $this->ctc()->pluginPath . 'includes/forms/at-import.php' ); ?>
|
45 |
<div id="view_parnt_options_panel"
|
46 |
class="ctc-option-panel<?php echo 'view_parnt_options' == $active_tab ? ' ctc-option-panel-active' : ''; ?>" <?php echo $hidechild; ?>> </div>
|
47 |
<?php
|
48 |
+
if ( '' == $hidechild ):
|
49 |
include ( $this->ctc()->pluginPath . 'includes/forms/files.php' );
|
50 |
endif;
|
51 |
+
do_action( 'chld_thm_cfg_panels', $this->ctc(), $active_tab, $hidechild );
|
52 |
endif; ?>
|
53 |
</div>
|
54 |
<?php
|
includes/forms/parent-child.php
CHANGED
@@ -1,5 +1,5 @@
|
|
1 |
<?php
|
2 |
-
if (!defined('ABSPATH')) exit;
|
3 |
// Parent/Child Panel
|
4 |
?>
|
5 |
|
@@ -7,8 +7,8 @@ if (!defined('ABSPATH')) exit;
|
|
7 |
<form id="ctc_load_form" method="post" action="?page=<?php echo CHLD_THM_CFG_MENU; ?>">
|
8 |
<?php
|
9 |
wp_nonce_field( 'ctc_update' );
|
10 |
-
if (has_action('chld_thm_cfg_controls')):
|
11 |
-
if ('' == $hidechild) do_action('chld_thm_cfg_controls', $this->ctc());
|
12 |
$themeonly = 'style="display:none"';
|
13 |
else:
|
14 |
$themeonly = '';
|
@@ -17,159 +17,159 @@ if (!defined('ABSPATH')) exit;
|
|
17 |
<div class="ctc-theme-only" <?php echo 'theme' != $configtype ? $themeonly : ''; ?>>
|
18 |
<div class="ctc-input-row clearfix" id="input_row_parnt">
|
19 |
<div class="ctc-input-cell"> <strong>
|
20 |
-
<?php _e('Parent Theme', 'chld_thm_cfg'); ?>
|
21 |
</strong> </div>
|
22 |
<div class="ctc-input-cell">
|
23 |
-
<?php $this->render_theme_menu('parnt', $parent); ?>
|
24 |
</div>
|
25 |
</div>
|
26 |
<div class="ctc-input-row clearfix" id="input_row_child">
|
27 |
<div class="ctc-input-cell"> <strong>
|
28 |
-
<?php _e('Child Theme', 'chld_thm_cfg'); ?>
|
29 |
</strong> </div>
|
30 |
<div class="ctc-input-cell">
|
31 |
<input class="ctc-radio" id="ctc_child_type_new" name="ctc_child_type" type="radio" value="new"
|
32 |
-
<?php echo (!empty($hidechild) ? 'checked' : ''); ?>
|
33 |
<?php echo $hidechild;?> />
|
34 |
<label for="ctc_child_type_new">
|
35 |
-
<?php _e('Create New Child Theme', 'chld_thm_cfg'); ?>
|
36 |
</label>
|
37 |
</div>
|
38 |
<div class="ctc-input-cell">
|
39 |
<input class="ctc-radio" id="ctc_child_type_existing" name="ctc_child_type" type="radio" value="existing"
|
40 |
-
<?php echo (empty($hidechild) ? 'checked' : ''); ?>
|
41 |
<?php echo $hidechild; ?>/>
|
42 |
|
43 |
<label for="ctc_child_type_existing" <?php echo $hidechild;?>>
|
44 |
-
<?php _e('Use Existing Child Theme', 'chld_thm_cfg'); ?>
|
45 |
</label>
|
46 |
</div>
|
47 |
<div class="ctc-input-cell" style="clear:both"> <strong> </strong> </div>
|
48 |
<div class="ctc-input-cell" >
|
49 |
-
<input class="ctc_text" id="ctc_child_template" name="ctc_child_template" type="text" placeholder="<?php _e('Theme Slug', 'chld_thm_cfg'); ?>" autocomplete="off"/>
|
50 |
</div>
|
51 |
-
<?php if ('' == $hidechild): ?>
|
52 |
<div class="ctc-input-cell">
|
53 |
-
<?php $this->render_theme_menu('child', $child); ?>
|
54 |
</div>
|
55 |
<?php endif; ?>
|
56 |
</div>
|
57 |
<div class="ctc-input-row clearfix" id="input_row_child_name">
|
58 |
<div class="ctc-input-cell"> <strong>
|
59 |
-
<?php _e('Child Theme Name', 'chld_thm_cfg'); ?>
|
60 |
</strong> </div>
|
61 |
<div class="ctc-input-cell">
|
62 |
<input class="ctc_text" id="ctc_child_name" name="ctc_child_name" type="text"
|
63 |
-
value="<?php echo esc_attr($css->get_prop('child_name')); ?>" placeholder="<?php _e('Theme Name', 'chld_thm_cfg'); ?>" autocomplete="off" />
|
64 |
</div>
|
65 |
</div>
|
66 |
</div>
|
67 |
<div class="ctc-input-row clearfix">
|
68 |
<div class="ctc-input-cell"> <strong>
|
69 |
-
<?php _e('Author', 'chld_thm_cfg'); ?>
|
70 |
</strong> </div>
|
71 |
<div class="ctc-input-cell">
|
72 |
<input class="ctc_text" id="ctc_child_author" name="ctc_child_author" type="text"
|
73 |
-
value="<?php echo esc_attr($css->get_prop('author')); ?>" placeholder="<?php _e('Author', 'chld_thm_cfg'); ?>" autocomplete="off" />
|
74 |
</div>
|
75 |
</div>
|
76 |
<div class="ctc-input-row clearfix">
|
77 |
<div class="ctc-input-cell"> <strong>
|
78 |
-
<?php _e('Version', 'chld_thm_cfg'); ?>
|
79 |
</strong> </div>
|
80 |
<div class="ctc-input-cell">
|
81 |
<input class="ctc_text" id="ctc_child_version" name="ctc_child_version" type="text"
|
82 |
-
value="<?php echo esc_attr($css->get_prop('version')); ?>" placeholder="<?php _e('Version', 'chld_thm_cfg'); ?>" autocomplete="off" />
|
83 |
</div>
|
84 |
</div>
|
85 |
<div class="ctc-theme-only" <?php echo 'theme' != $configtype ? $themeonly : ''; ?>>
|
86 |
<div class="ctc-input-row clearfix">
|
87 |
<div class="ctc-input-cell"> <strong>
|
88 |
-
<?php _e('Copy Parent Theme Menus, Widgets and other Options', 'chld_thm_cfg'); ?>
|
89 |
</strong> </div>
|
90 |
<div class="ctc-input-cell">
|
91 |
<input class="ctc_checkbox" id="ctc_parent_mods" name="ctc_parent_mods" type="checkbox"
|
92 |
value="1" />
|
93 |
</div>
|
94 |
<div class="ctc-input-cell"> <strong>
|
95 |
-
<?php _e('NOTE:', 'chld_thm_cfg'); ?>
|
96 |
</strong>
|
97 |
-
<?php _e( 'This will overwrite child theme options you may have already set.', 'chld_thm_cfg'); ?>
|
98 |
</div>
|
99 |
</div>
|
100 |
-
<?php if ('' == $hidechild): ?>
|
101 |
<div class="ctc-input-row clearfix">
|
102 |
<div class="ctc-input-cell"> <strong>
|
103 |
-
<?php _e('Backup current stylesheet', 'chld_thm_cfg'); ?>
|
104 |
</strong> </div>
|
105 |
<div class="ctc-input-cell">
|
106 |
<input class="ctc_checkbox" id="ctc_backup" name="ctc_backup" type="checkbox"
|
107 |
value="1" />
|
108 |
</div>
|
109 |
<div class="ctc-input-cell"> <strong>
|
110 |
-
<?php _e('NOTE:', 'chld_thm_cfg'); ?>
|
111 |
</strong>
|
112 |
-
<?php _e( 'This creates a copy of the current stylesheet before applying changes. You can remove old backup files using the Files tab.', 'chld_thm_cfg'); ?>
|
113 |
</div>
|
114 |
</div>
|
115 |
<?php
|
116 |
endif;
|
117 |
-
$parent_handling = (isset($css->enqueue) ? $css->enqueue : ($mustimport ? 'import' : 'enqueue'));
|
118 |
?>
|
119 |
<div class="ctc-input-row clearfix">
|
120 |
<div class="ctc-input-cell"> <strong>
|
121 |
-
<?php _e('Parent stylesheet handling:', 'chld_thm_cfg'); ?>
|
122 |
</strong> </div>
|
123 |
<div class="ctc-input-cell">
|
124 |
<label>
|
125 |
<input class="ctc_radio" id="ctc_parent_enqueue_enqueue" name="ctc_parent_enqueue" type="radio"
|
126 |
-
value="enqueue" <?php checked('enqueue', $parent_handling); ?>/>
|
127 |
-
<?php _e('<link> (default)', 'chld_thm_cfg'); ?>
|
128 |
</label>
|
129 |
<br/>
|
130 |
<label>
|
131 |
<input class="ctc_radio" id="ctc_parent_enqueue_import" name="ctc_parent_enqueue" type="radio"
|
132 |
-
value="import" <?php checked('import', $parent_handling); ?>/>
|
133 |
-
<?php _e('@import', 'chld_thm_cfg'); ?>
|
134 |
</label>
|
135 |
<br/>
|
136 |
<label>
|
137 |
<input class="ctc_radio" id="ctc_parent_enqueue_none" name="ctc_parent_enqueue" type="radio"
|
138 |
-
value="none" <?php checked('none', $parent_handling); ?>/>
|
139 |
-
<?php _e('none (handled by theme)', 'chld_thm_cfg'); ?>
|
140 |
</label>
|
141 |
</div>
|
142 |
<div class="ctc-input-cell"> <strong>
|
143 |
-
<?php _e('NOTE:', 'chld_thm_cfg'); ?>
|
144 |
-
<?php if ($mustimport) _e('This theme does not currently enqueue the stylesheet and must use the @import option to render correctly.', 'chld_thm_cfg'); ?>
|
145 |
</strong>
|
146 |
-
<?php _e( "Select @import for older themes that do not enqueue the stylesheet. Select 'none' if core styles are automatically loaded for child themes. Select '<link>' if unsure.", 'chld_thm_cfg'); ?>
|
147 |
</div>
|
148 |
</div>
|
149 |
-
<?php if ('' == $hidechild): ?>
|
150 |
<div class="ctc-input-row clearfix">
|
151 |
<div class="ctc-input-cell ctc-section-toggle" id="ctc_revert_css"> <strong>
|
152 |
-
<?php _e('Reset/Restore from backup:', 'chld_thm_cfg'); ?>
|
153 |
</strong> </div>
|
154 |
<div class="ctc-input-cell-wide ctc-section-toggle-content" id="ctc_revert_css_content">
|
155 |
<label>
|
156 |
<input class="ctc_checkbox" id="ctc_revert_none" name="ctc_revert" type="radio"
|
157 |
value="" checked="" />
|
158 |
-
<?php _e('Leave unchanged', 'chld_thm_cfg');?>
|
159 |
</label>
|
160 |
<br/>
|
161 |
<label>
|
162 |
<input class="ctc_checkbox" id="ctc_revert_all" name="ctc_revert" type="radio"
|
163 |
value="all" />
|
164 |
-
<?php _e('Reset all', 'chld_thm_cfg');?>
|
165 |
</label>
|
166 |
<br/>
|
167 |
<?php
|
168 |
-
foreach ($this->ctc()->get_files($child, 'backup') as $backup => $label): ?>
|
169 |
<label>
|
170 |
<input class="ctc_checkbox" id="ctc_revert_<?php echo $backup; ?>" name="ctc_revert" type="radio"
|
171 |
value="<?php echo $backup; ?>" />
|
172 |
-
<?php echo __('Restore backup from', 'chld_thm_cfg') . ' ' . $label; ?></label>
|
173 |
<br/>
|
174 |
<?php
|
175 |
endforeach;
|
@@ -177,18 +177,18 @@ if (!defined('ABSPATH')) exit;
|
|
177 |
</div>
|
178 |
</div>
|
179 |
<?php endif;
|
180 |
-
$stylesheets = $this->ctc()->get_files($parent, 'stylesheet');
|
181 |
-
if (count($stylesheets)):?>
|
182 |
<div class="ctc-input-row clearfix">
|
183 |
<div class="ctc-input-cell ctc-section-toggle" id="ctc_additional_css_files"> <strong>
|
184 |
-
<?php _e('Parse additional stylesheets:', 'chld_thm_cfg'); ?>
|
185 |
</strong> </div>
|
186 |
<div class="ctc-input-cell-wide ctc-section-toggle-content" id="ctc_additional_css_files_content">
|
187 |
<p style="margin-top:0">
|
188 |
-
<?php _e('Stylesheets that are currently being loaded by the parent theme are automatically selected below (except for Bootstrap stylesheets which add a large amount data to the configuration). To further reduce overhead, select only the additional stylesheets you wish to customize.', 'chld_thm_cfg'); ?>
|
189 |
</p>
|
190 |
<?php
|
191 |
-
foreach ($stylesheets as $stylesheet): ?>
|
192 |
<div class="ctc-input-cell">
|
193 |
<label>
|
194 |
<input class="ctc_checkbox" name="ctc_additional_css[]" type="checkbox"
|
@@ -204,7 +204,7 @@ if (!defined('ABSPATH')) exit;
|
|
204 |
<div class="ctc-input-cell"> <strong> </strong> </div>
|
205 |
<div class="ctc-input-cell">
|
206 |
<input class="ctc_submit button button-primary" id="ctc_load_styles" name="ctc_load_styles" type="submit"
|
207 |
-
value="<?php _e('Generate/Rebuild Child Theme Files', 'chld_thm_cfg'); ?>" disabled />
|
208 |
</div>
|
209 |
</div>
|
210 |
</form>
|
1 |
<?php
|
2 |
+
if ( !defined( 'ABSPATH' ) ) exit;
|
3 |
// Parent/Child Panel
|
4 |
?>
|
5 |
|
7 |
<form id="ctc_load_form" method="post" action="?page=<?php echo CHLD_THM_CFG_MENU; ?>">
|
8 |
<?php
|
9 |
wp_nonce_field( 'ctc_update' );
|
10 |
+
if ( has_action( 'chld_thm_cfg_controls' ) ):
|
11 |
+
if ( '' == $hidechild ) do_action( 'chld_thm_cfg_controls', $this->ctc() );
|
12 |
$themeonly = 'style="display:none"';
|
13 |
else:
|
14 |
$themeonly = '';
|
17 |
<div class="ctc-theme-only" <?php echo 'theme' != $configtype ? $themeonly : ''; ?>>
|
18 |
<div class="ctc-input-row clearfix" id="input_row_parnt">
|
19 |
<div class="ctc-input-cell"> <strong>
|
20 |
+
<?php _e( 'Parent Theme', 'chld_thm_cfg' ); ?>
|
21 |
</strong> </div>
|
22 |
<div class="ctc-input-cell">
|
23 |
+
<?php $this->render_theme_menu( 'parnt', $parent ); ?>
|
24 |
</div>
|
25 |
</div>
|
26 |
<div class="ctc-input-row clearfix" id="input_row_child">
|
27 |
<div class="ctc-input-cell"> <strong>
|
28 |
+
<?php _e( 'Child Theme', 'chld_thm_cfg' ); ?>
|
29 |
</strong> </div>
|
30 |
<div class="ctc-input-cell">
|
31 |
<input class="ctc-radio" id="ctc_child_type_new" name="ctc_child_type" type="radio" value="new"
|
32 |
+
<?php echo ( !empty( $hidechild ) ? 'checked' : '' ); ?>
|
33 |
<?php echo $hidechild;?> />
|
34 |
<label for="ctc_child_type_new">
|
35 |
+
<?php _e( 'Create New Child Theme', 'chld_thm_cfg' ); ?>
|
36 |
</label>
|
37 |
</div>
|
38 |
<div class="ctc-input-cell">
|
39 |
<input class="ctc-radio" id="ctc_child_type_existing" name="ctc_child_type" type="radio" value="existing"
|
40 |
+
<?php echo ( empty( $hidechild ) ? 'checked' : '' ); ?>
|
41 |
<?php echo $hidechild; ?>/>
|
42 |
|
43 |
<label for="ctc_child_type_existing" <?php echo $hidechild;?>>
|
44 |
+
<?php _e( 'Use Existing Child Theme', 'chld_thm_cfg' ); ?>
|
45 |
</label>
|
46 |
</div>
|
47 |
<div class="ctc-input-cell" style="clear:both"> <strong> </strong> </div>
|
48 |
<div class="ctc-input-cell" >
|
49 |
+
<input class="ctc_text" id="ctc_child_template" name="ctc_child_template" type="text" placeholder="<?php _e( 'Theme Slug', 'chld_thm_cfg' ); ?>" autocomplete="off"/>
|
50 |
</div>
|
51 |
+
<?php if ( '' == $hidechild ): ?>
|
52 |
<div class="ctc-input-cell">
|
53 |
+
<?php $this->render_theme_menu( 'child', $child ); ?>
|
54 |
</div>
|
55 |
<?php endif; ?>
|
56 |
</div>
|
57 |
<div class="ctc-input-row clearfix" id="input_row_child_name">
|
58 |
<div class="ctc-input-cell"> <strong>
|
59 |
+
<?php _e( 'Child Theme Name', 'chld_thm_cfg' ); ?>
|
60 |
</strong> </div>
|
61 |
<div class="ctc-input-cell">
|
62 |
<input class="ctc_text" id="ctc_child_name" name="ctc_child_name" type="text"
|
63 |
+
value="<?php echo esc_attr( $css->get_prop( 'child_name' ) ); ?>" placeholder="<?php _e( 'Theme Name', 'chld_thm_cfg' ); ?>" autocomplete="off" />
|
64 |
</div>
|
65 |
</div>
|
66 |
</div>
|
67 |
<div class="ctc-input-row clearfix">
|
68 |
<div class="ctc-input-cell"> <strong>
|
69 |
+
<?php _e( 'Author', 'chld_thm_cfg' ); ?>
|
70 |
</strong> </div>
|
71 |
<div class="ctc-input-cell">
|
72 |
<input class="ctc_text" id="ctc_child_author" name="ctc_child_author" type="text"
|
73 |
+
value="<?php echo esc_attr( $css->get_prop( 'author' ) ); ?>" placeholder="<?php _e( 'Author', 'chld_thm_cfg' ); ?>" autocomplete="off" />
|
74 |
</div>
|
75 |
</div>
|
76 |
<div class="ctc-input-row clearfix">
|
77 |
<div class="ctc-input-cell"> <strong>
|
78 |
+
<?php _e( 'Version', 'chld_thm_cfg' ); ?>
|
79 |
</strong> </div>
|
80 |
<div class="ctc-input-cell">
|
81 |
<input class="ctc_text" id="ctc_child_version" name="ctc_child_version" type="text"
|
82 |
+
value="<?php echo esc_attr( $css->get_prop( 'version' ) ); ?>" placeholder="<?php _e( 'Version', 'chld_thm_cfg' ); ?>" autocomplete="off" />
|
83 |
</div>
|
84 |
</div>
|
85 |
<div class="ctc-theme-only" <?php echo 'theme' != $configtype ? $themeonly : ''; ?>>
|
86 |
<div class="ctc-input-row clearfix">
|
87 |
<div class="ctc-input-cell"> <strong>
|
88 |
+
<?php _e( 'Copy Parent Theme Menus, Widgets and other Options', 'chld_thm_cfg' ); ?>
|
89 |
</strong> </div>
|
90 |
<div class="ctc-input-cell">
|
91 |
<input class="ctc_checkbox" id="ctc_parent_mods" name="ctc_parent_mods" type="checkbox"
|
92 |
value="1" />
|
93 |
</div>
|
94 |
<div class="ctc-input-cell"> <strong>
|
95 |
+
<?php _e( 'NOTE:', 'chld_thm_cfg' ); ?>
|
96 |
</strong>
|
97 |
+
<?php _e( 'This will overwrite child theme options you may have already set.', 'chld_thm_cfg' ); ?>
|
98 |
</div>
|
99 |
</div>
|
100 |
+
<?php if ( '' == $hidechild ): ?>
|
101 |
<div class="ctc-input-row clearfix">
|
102 |
<div class="ctc-input-cell"> <strong>
|
103 |
+
<?php _e( 'Backup current stylesheet', 'chld_thm_cfg' ); ?>
|
104 |
</strong> </div>
|
105 |
<div class="ctc-input-cell">
|
106 |
<input class="ctc_checkbox" id="ctc_backup" name="ctc_backup" type="checkbox"
|
107 |
value="1" />
|
108 |
</div>
|
109 |
<div class="ctc-input-cell"> <strong>
|
110 |
+
<?php _e( 'NOTE:', 'chld_thm_cfg' ); ?>
|
111 |
</strong>
|
112 |
+
<?php _e( 'This creates a copy of the current stylesheet before applying changes. You can remove old backup files using the Files tab.', 'chld_thm_cfg' ); ?>
|
113 |
</div>
|
114 |
</div>
|
115 |
<?php
|
116 |
endif;
|
117 |
+
$parent_handling = ( isset( $css->enqueue ) ? $css->enqueue : ( $mustimport ? 'import' : 'enqueue' ) );
|
118 |
?>
|
119 |
<div class="ctc-input-row clearfix">
|
120 |
<div class="ctc-input-cell"> <strong>
|
121 |
+
<?php _e( 'Parent stylesheet handling:', 'chld_thm_cfg' ); ?>
|
122 |
</strong> </div>
|
123 |
<div class="ctc-input-cell">
|
124 |
<label>
|
125 |
<input class="ctc_radio" id="ctc_parent_enqueue_enqueue" name="ctc_parent_enqueue" type="radio"
|
126 |
+
value="enqueue" <?php checked( 'enqueue', $parent_handling ); ?>/>
|
127 |
+
<?php _e( '<link> (default)', 'chld_thm_cfg' ); ?>
|
128 |
</label>
|
129 |
<br/>
|
130 |
<label>
|
131 |
<input class="ctc_radio" id="ctc_parent_enqueue_import" name="ctc_parent_enqueue" type="radio"
|
132 |
+
value="import" <?php checked( 'import', $parent_handling ); ?>/>
|
133 |
+
<?php _e( '@import', 'chld_thm_cfg' ); ?>
|
134 |
</label>
|
135 |
<br/>
|
136 |
<label>
|
137 |
<input class="ctc_radio" id="ctc_parent_enqueue_none" name="ctc_parent_enqueue" type="radio"
|
138 |
+
value="none" <?php checked( 'none', $parent_handling ); ?>/>
|
139 |
+
<?php _e( 'none (handled by theme)', 'chld_thm_cfg' ); ?>
|
140 |
</label>
|
141 |
</div>
|
142 |
<div class="ctc-input-cell"> <strong>
|
143 |
+
<?php _e( 'NOTE:', 'chld_thm_cfg' ); ?>
|
144 |
+
<?php if ( $mustimport ) _e( 'This theme does not currently enqueue the stylesheet and must use the @import option to render correctly.', 'chld_thm_cfg' ); ?>
|
145 |
</strong>
|
146 |
+
<?php _e( "Select @import for older themes that do not enqueue the stylesheet. Select 'none' if core styles are automatically loaded for child themes. Select '<link>' if unsure.", 'chld_thm_cfg' ); ?>
|
147 |
</div>
|
148 |
</div>
|
149 |
+
<?php if ( '' == $hidechild ): ?>
|
150 |
<div class="ctc-input-row clearfix">
|
151 |
<div class="ctc-input-cell ctc-section-toggle" id="ctc_revert_css"> <strong>
|
152 |
+
<?php _e( 'Reset/Restore from backup:', 'chld_thm_cfg' ); ?>
|
153 |
</strong> </div>
|
154 |
<div class="ctc-input-cell-wide ctc-section-toggle-content" id="ctc_revert_css_content">
|
155 |
<label>
|
156 |
<input class="ctc_checkbox" id="ctc_revert_none" name="ctc_revert" type="radio"
|
157 |
value="" checked="" />
|
158 |
+
<?php _e( 'Leave unchanged', 'chld_thm_cfg' );?>
|
159 |
</label>
|
160 |
<br/>
|
161 |
<label>
|
162 |
<input class="ctc_checkbox" id="ctc_revert_all" name="ctc_revert" type="radio"
|
163 |
value="all" />
|
164 |
+
<?php _e( 'Reset all', 'chld_thm_cfg' );?>
|
165 |
</label>
|
166 |
<br/>
|
167 |
<?php
|
168 |
+
foreach ( $this->ctc()->get_files( $child, 'backup' ) as $backup => $label ): ?>
|
169 |
<label>
|
170 |
<input class="ctc_checkbox" id="ctc_revert_<?php echo $backup; ?>" name="ctc_revert" type="radio"
|
171 |
value="<?php echo $backup; ?>" />
|
172 |
+
<?php echo __( 'Restore backup from', 'chld_thm_cfg' ) . ' ' . $label; ?></label>
|
173 |
<br/>
|
174 |
<?php
|
175 |
endforeach;
|
177 |
</div>
|
178 |
</div>
|
179 |
<?php endif;
|
180 |
+
$stylesheets = $this->ctc()->get_files( $parent, 'stylesheet' );
|
181 |
+
if ( count( $stylesheets ) ):?>
|
182 |
<div class="ctc-input-row clearfix">
|
183 |
<div class="ctc-input-cell ctc-section-toggle" id="ctc_additional_css_files"> <strong>
|
184 |
+
<?php _e( 'Parse additional stylesheets:', 'chld_thm_cfg' ); ?>
|
185 |
</strong> </div>
|
186 |
<div class="ctc-input-cell-wide ctc-section-toggle-content" id="ctc_additional_css_files_content">
|
187 |
<p style="margin-top:0">
|
188 |
+
<?php _e( 'Stylesheets that are currently being loaded by the parent theme are automatically selected below (except for Bootstrap stylesheets which add a large amount data to the configuration). To further reduce overhead, select only the additional stylesheets you wish to customize.', 'chld_thm_cfg' ); ?>
|
189 |
</p>
|
190 |
<?php
|
191 |
+
foreach ( $stylesheets as $stylesheet ): ?>
|
192 |
<div class="ctc-input-cell">
|
193 |
<label>
|
194 |
<input class="ctc_checkbox" name="ctc_additional_css[]" type="checkbox"
|
204 |
<div class="ctc-input-cell"> <strong> </strong> </div>
|
205 |
<div class="ctc-input-cell">
|
206 |
<input class="ctc_submit button button-primary" id="ctc_load_styles" name="ctc_load_styles" type="submit"
|
207 |
+
value="<?php _e( 'Generate/Rebuild Child Theme Files', 'chld_thm_cfg' ); ?>" disabled />
|
208 |
</div>
|
209 |
</div>
|
210 |
</form>
|
includes/forms/query-selector.php
CHANGED
@@ -1,5 +1,5 @@
|
|
1 |
<?php
|
2 |
-
if (!defined('ABSPATH')) exit;
|
3 |
// Query/Selector Panel
|
4 |
?>
|
5 |
|
@@ -8,7 +8,7 @@ if (!defined('ABSPATH')) exit;
|
|
8 |
<form id="ctc_query_selector_form" method="post" action="?page=<?php echo CHLD_THM_CFG_MENU; ?>">
|
9 |
<div class="ctc-input-row clearfix" id="input_row_query">
|
10 |
<div class="ctc-input-cell"> <strong>
|
11 |
-
<?php _e('Query', 'chld_thm_cfg'); ?>
|
12 |
</strong> </div>
|
13 |
<div class="ctc-input-cell" id="ctc_sel_ovrd_query_selected"> </div>
|
14 |
<div class="ctc-input-cell">
|
@@ -19,7 +19,7 @@ if (!defined('ABSPATH')) exit;
|
|
19 |
</div>
|
20 |
<div class="ctc-input-row clearfix" id="input_row_selector">
|
21 |
<div class="ctc-input-cell"> <strong>
|
22 |
-
<?php _e('Selector', 'chld_thm_cfg'); ?>
|
23 |
</strong> <a href="#" class="ctc-rewrite-toggle"></a></div>
|
24 |
<div class="ctc-input-cell" id="ctc_sel_ovrd_selector_selected"> </div>
|
25 |
<div class="ctc-input-cell">
|
@@ -32,7 +32,7 @@ if (!defined('ABSPATH')) exit;
|
|
32 |
<div class="ctc-selector-row clearfix" id="ctc_sel_ovrd_rule_inputs_container" style="display:none">
|
33 |
<div class="ctc-input-row clearfix">
|
34 |
<div class="ctc-input-cell"><strong>
|
35 |
-
<?php _e('Sample', 'chld_thm_cfg'); ?>
|
36 |
</strong></div>
|
37 |
<div class="ctc-input-cell clearfix" style="max-height:150px;overflow:hidden">
|
38 |
<div class="ctc-swatch" id="ctc_child_all_0_swatch"><?php echo $this->ctc()->swatch_text; ?></div>
|
@@ -40,26 +40,26 @@ if (!defined('ABSPATH')) exit;
|
|
40 |
<div id="ctc_status_sel_val"></div>
|
41 |
<div class="ctc-input-cell ctc-button-cell" id="ctc_save_query_selector_cell">
|
42 |
<input type="button" class="button button-primary ctc-save-input" id="ctc_save_query_selector"
|
43 |
-
name="ctc_save_query_selector" value="<?php _e('Save', 'chld_thm_cfg'); ?>" disabled />
|
44 |
<input type="hidden" id="ctc_sel_ovrd_qsid"
|
45 |
name="ctc_sel_ovrd_qsid" value="" />
|
46 |
</div>
|
47 |
</div>
|
48 |
<div class="ctc-input-row clearfix" id="ctc_sel_ovrd_rule_header" style="display:none">
|
49 |
<div class="ctc-input-cell"> <strong>
|
50 |
-
<?php _e('Rule', 'chld_thm_cfg'); ?>
|
51 |
</strong> </div>
|
52 |
<div class="ctc-input-cell"> <strong>
|
53 |
-
<?php _e('Parent Value', 'chld_thm_cfg'); ?>
|
54 |
</strong> </div>
|
55 |
<div class="ctc-input-cell"> <strong>
|
56 |
-
<?php _e('Child Value', 'chld_thm_cfg'); ?>
|
57 |
</strong> </div>
|
58 |
</div>
|
59 |
<div id="ctc_sel_ovrd_rule_inputs" style="display:none"> </div>
|
60 |
<div class="ctc-input-row clearfix" id="ctc_sel_ovrd_new_rule" style="display:none">
|
61 |
<div class="ctc-input-cell"> <strong>
|
62 |
-
<?php _e('New Rule', 'chld_thm_cfg'); ?>
|
63 |
</strong> </div>
|
64 |
<div class="ctc-input-cell">
|
65 |
<div class="ui-widget">
|
@@ -69,7 +69,7 @@ if (!defined('ABSPATH')) exit;
|
|
69 |
</div>
|
70 |
<div class="ctc-input-row clearfix" id="input_row_selector">
|
71 |
<div class="ctc-input-cell"> <strong>
|
72 |
-
<?php _e('Order', 'chld_thm_cfg'); ?>
|
73 |
</strong> </div>
|
74 |
<div class="ctc-input-cell" id="ctc_child_load_order_container"> </div>
|
75 |
</div>
|
@@ -78,12 +78,12 @@ if (!defined('ABSPATH')) exit;
|
|
78 |
<div class="ctc-input-cell">
|
79 |
<div class="ctc-textarea-button-cell" id="ctc_save_query_selector_cell">
|
80 |
<input type="button" class="button ctc-save-input" id="ctc_save_new_selectors"
|
81 |
-
name="ctc_save_new_selectors" value="<?php _e('Save', 'chld_thm_cfg'); ?>" disabled />
|
82 |
</div>
|
83 |
<strong>
|
84 |
-
<?php _e('Raw CSS', 'chld_thm_cfg'); ?>
|
85 |
</strong>
|
86 |
-
<p><?php _e('Use to enter shorthand CSS or new @media queries and selectors.', 'chld_thm_cfg');?></p><p><?php _e('Values entered here are merged into existing child styles or added to the child stylesheet if they do not exist in the parent.', 'chld_thm_cfg'); ?></p>
|
87 |
</div>
|
88 |
<div class="ctc-input-cell-wide">
|
89 |
<textarea id="ctc_new_selectors" name="ctc_new_selectors" wrap="off"></textarea>
|
1 |
<?php
|
2 |
+
if ( !defined( 'ABSPATH' ) ) exit;
|
3 |
// Query/Selector Panel
|
4 |
?>
|
5 |
|
8 |
<form id="ctc_query_selector_form" method="post" action="?page=<?php echo CHLD_THM_CFG_MENU; ?>">
|
9 |
<div class="ctc-input-row clearfix" id="input_row_query">
|
10 |
<div class="ctc-input-cell"> <strong>
|
11 |
+
<?php _e( 'Query', 'chld_thm_cfg' ); ?>
|
12 |
</strong> </div>
|
13 |
<div class="ctc-input-cell" id="ctc_sel_ovrd_query_selected"> </div>
|
14 |
<div class="ctc-input-cell">
|
19 |
</div>
|
20 |
<div class="ctc-input-row clearfix" id="input_row_selector">
|
21 |
<div class="ctc-input-cell"> <strong>
|
22 |
+
<?php _e( 'Selector', 'chld_thm_cfg' ); ?>
|
23 |
</strong> <a href="#" class="ctc-rewrite-toggle"></a></div>
|
24 |
<div class="ctc-input-cell" id="ctc_sel_ovrd_selector_selected"> </div>
|
25 |
<div class="ctc-input-cell">
|
32 |
<div class="ctc-selector-row clearfix" id="ctc_sel_ovrd_rule_inputs_container" style="display:none">
|
33 |
<div class="ctc-input-row clearfix">
|
34 |
<div class="ctc-input-cell"><strong>
|
35 |
+
<?php _e( 'Sample', 'chld_thm_cfg' ); ?>
|
36 |
</strong></div>
|
37 |
<div class="ctc-input-cell clearfix" style="max-height:150px;overflow:hidden">
|
38 |
<div class="ctc-swatch" id="ctc_child_all_0_swatch"><?php echo $this->ctc()->swatch_text; ?></div>
|
40 |
<div id="ctc_status_sel_val"></div>
|
41 |
<div class="ctc-input-cell ctc-button-cell" id="ctc_save_query_selector_cell">
|
42 |
<input type="button" class="button button-primary ctc-save-input" id="ctc_save_query_selector"
|
43 |
+
name="ctc_save_query_selector" value="<?php _e( 'Save', 'chld_thm_cfg' ); ?>" disabled />
|
44 |
<input type="hidden" id="ctc_sel_ovrd_qsid"
|
45 |
name="ctc_sel_ovrd_qsid" value="" />
|
46 |
</div>
|
47 |
</div>
|
48 |
<div class="ctc-input-row clearfix" id="ctc_sel_ovrd_rule_header" style="display:none">
|
49 |
<div class="ctc-input-cell"> <strong>
|
50 |
+
<?php _e( 'Rule', 'chld_thm_cfg' ); ?>
|
51 |
</strong> </div>
|
52 |
<div class="ctc-input-cell"> <strong>
|
53 |
+
<?php _e( 'Parent Value', 'chld_thm_cfg' ); ?>
|
54 |
</strong> </div>
|
55 |
<div class="ctc-input-cell"> <strong>
|
56 |
+
<?php _e( 'Child Value', 'chld_thm_cfg' ); ?>
|
57 |
</strong> </div>
|
58 |
</div>
|
59 |
<div id="ctc_sel_ovrd_rule_inputs" style="display:none"> </div>
|
60 |
<div class="ctc-input-row clearfix" id="ctc_sel_ovrd_new_rule" style="display:none">
|
61 |
<div class="ctc-input-cell"> <strong>
|
62 |
+
<?php _e( 'New Rule', 'chld_thm_cfg' ); ?>
|
63 |
</strong> </div>
|
64 |
<div class="ctc-input-cell">
|
65 |
<div class="ui-widget">
|
69 |
</div>
|
70 |
<div class="ctc-input-row clearfix" id="input_row_selector">
|
71 |
<div class="ctc-input-cell"> <strong>
|
72 |
+
<?php _e( 'Order', 'chld_thm_cfg' ); ?>
|
73 |
</strong> </div>
|
74 |
<div class="ctc-input-cell" id="ctc_child_load_order_container"> </div>
|
75 |
</div>
|
78 |
<div class="ctc-input-cell">
|
79 |
<div class="ctc-textarea-button-cell" id="ctc_save_query_selector_cell">
|
80 |
<input type="button" class="button ctc-save-input" id="ctc_save_new_selectors"
|
81 |
+
name="ctc_save_new_selectors" value="<?php _e( 'Save', 'chld_thm_cfg' ); ?>" disabled />
|
82 |
</div>
|
83 |
<strong>
|
84 |
+
<?php _e( 'Raw CSS', 'chld_thm_cfg' ); ?>
|
85 |
</strong>
|
86 |
+
<p><?php _e( 'Use to enter shorthand CSS or new @media queries and selectors.', 'chld_thm_cfg' );?></p><p><?php _e( 'Values entered here are merged into existing child styles or added to the child stylesheet if they do not exist in the parent.', 'chld_thm_cfg' ); ?></p>
|
87 |
</div>
|
88 |
<div class="ctc-input-cell-wide">
|
89 |
<textarea id="ctc_new_selectors" name="ctc_new_selectors" wrap="off"></textarea>
|
includes/forms/related.php
CHANGED
@@ -1 +1 @@
|
|
1 |
-
<span style="float:right;margin-left:2em;margin-top:-6px;text-shadow:1px 2px 0 #fff"><strong><?php _e('New user?','chld_thm_cfg'); ?> <span style="color:#F1823B"><?php _e('Click help', 'chld_thm_cfg'); ?></span></strong> <i class="dashicons dashicons-arrow-right-alt" style="color:#F1823B"></i></span><a href="http://www.lilaeamedia.com/plugins/child-theme-plugin-styles/" target="_blank" title="<?php _e('Get CTC for Plugins and other tools', 'chld_thm_cfg'); ?>" style="float:right"><img src="<?php echo $this->ctc()->pluginURL; ?>/css/lilaea-logo.png" height="36" width="145" alt="<?php _e('Lilaea Media - Responsive Tools for a Mobile World', 'chld_thm_cfg'); ?>" /></a>
|
1 |
+
<span style="float:right;margin-left:2em;margin-top:-6px;text-shadow:1px 2px 0 #fff"><strong><?php _e( 'New user?','chld_thm_cfg' ); ?> <span style="color:#F1823B"><?php _e( 'Click help', 'chld_thm_cfg' ); ?></span></strong> <i class="dashicons dashicons-arrow-right-alt" style="color:#F1823B"></i></span><a href="http://www.lilaeamedia.com/plugins/child-theme-plugin-styles/" target="_blank" title="<?php _e( 'Get CTC for Plugins and other tools', 'chld_thm_cfg' ); ?>" style="float:right"><img src="<?php echo $this->ctc()->pluginURL; ?>/css/lilaea-logo.png" height="36" width="145" alt="<?php _e( 'Lilaea Media - Responsive Tools for a Mobile World', 'chld_thm_cfg' ); ?>" /></a>
|
includes/forms/rule-value.php
CHANGED
@@ -1,5 +1,5 @@
|
|
1 |
<?php
|
2 |
-
if (!defined('ABSPATH')) exit;
|
3 |
// Rule/Value Panel
|
4 |
?>
|
5 |
|
@@ -9,7 +9,7 @@ if (!defined('ABSPATH')) exit;
|
|
9 |
<?php wp_nonce_field( 'ctc_update' ); ?>
|
10 |
<div class="ctc-input-row clearfix" id="ctc_input_row_rule_menu">
|
11 |
<div class="ctc-input-cell"> <strong>
|
12 |
-
<?php _e('Rule', 'chld_thm_cfg'); ?>
|
13 |
</strong> </div>
|
14 |
<div class="ctc-input-cell" id="ctc_rule_menu_selected"> </div>
|
15 |
<div id="ctc_status_rule_val"></div>
|
@@ -22,13 +22,13 @@ if (!defined('ABSPATH')) exit;
|
|
22 |
</div>
|
23 |
<div class="ctc-input-row clearfix" id="ctc_input_row_rule_header" style="display:none">
|
24 |
<div class="ctc-input-cell"> <strong>
|
25 |
-
<?php _e('Value', 'chld_thm_cfg'); ?>
|
26 |
</strong> </div>
|
27 |
<div class="ctc-input-cell"> <strong>
|
28 |
-
<?php _e('Sample', 'chld_thm_cfg'); ?>
|
29 |
</strong> </div>
|
30 |
<div class="ctc-input-cell"> <strong>
|
31 |
-
<?php _e('Selectors', 'chld_thm_cfg'); ?>
|
32 |
</strong> </div>
|
33 |
</div>
|
34 |
<div class="ctc-rule-value-input-container clearfix" id="ctc_rule_value_inputs" style="display:none"> </div>
|
1 |
<?php
|
2 |
+
if ( !defined( 'ABSPATH' ) ) exit;
|
3 |
// Rule/Value Panel
|
4 |
?>
|
5 |
|
9 |
<?php wp_nonce_field( 'ctc_update' ); ?>
|
10 |
<div class="ctc-input-row clearfix" id="ctc_input_row_rule_menu">
|
11 |
<div class="ctc-input-cell"> <strong>
|
12 |
+
<?php _e( 'Rule', 'chld_thm_cfg' ); ?>
|
13 |
</strong> </div>
|
14 |
<div class="ctc-input-cell" id="ctc_rule_menu_selected"> </div>
|
15 |
<div id="ctc_status_rule_val"></div>
|
22 |
</div>
|
23 |
<div class="ctc-input-row clearfix" id="ctc_input_row_rule_header" style="display:none">
|
24 |
<div class="ctc-input-cell"> <strong>
|
25 |
+
<?php _e( 'Value', 'chld_thm_cfg' ); ?>
|
26 |
</strong> </div>
|
27 |
<div class="ctc-input-cell"> <strong>
|
28 |
+
<?php _e( 'Sample', 'chld_thm_cfg' ); ?>
|
29 |
</strong> </div>
|
30 |
<div class="ctc-input-cell"> <strong>
|
31 |
+
<?php _e( 'Selectors', 'chld_thm_cfg' ); ?>
|
32 |
</strong> </div>
|
33 |
</div>
|
34 |
<div class="ctc-rule-value-input-container clearfix" id="ctc_rule_value_inputs" style="display:none"> </div>
|
includes/forms/tabs.php
CHANGED
@@ -1,5 +1,5 @@
|
|
1 |
<?php
|
2 |
-
if (!defined('ABSPATH')) exit;
|
3 |
// Tabs Bar
|
4 |
|
5 |
$active_tab = isset( $_GET[ 'tab' ] ) ? $_GET[ 'tab' ] : 'parent_child_options';
|
@@ -8,33 +8,33 @@ $active_tab = isset( $_GET[ 'tab' ] ) ? $_GET[ 'tab' ] : 'parent_child_options';
|
|
8 |
<h2 class="nav-tab-wrapper">
|
9 |
<a id="parent_child_options" href=""
|
10 |
class="nav-tab<?php echo 'parent_child_options' == $active_tab ? ' nav-tab-active' : ''; ?>">
|
11 |
-
<?php _e('Parent/Child', 'chld_thm_cfg'); ?>
|
12 |
</a>
|
13 |
-
<?php if ($enqueueset): ?>
|
14 |
<!----><a id="query_selector_options" href=""
|
15 |
class="nav-tab<?php echo 'query_selector_options' == $active_tab ? ' nav-tab-active' : ''; ?>" <?php echo $hidechild; ?>>
|
16 |
-
<?php _e('Query/Selector', 'chld_thm_cfg'); ?>
|
17 |
</a><!----><a id="rule_value_options" href=""
|
18 |
class="nav-tab<?php echo 'rule_value_options' == $active_tab ? ' nav-tab-active' : ''; ?>" <?php echo $hidechild; ?>>
|
19 |
-
<?php _e('Rule/Value', 'chld_thm_cfg'); ?>
|
20 |
</a><!----><a id="import_options" href=""
|
21 |
class="nav-tab<?php echo 'import_options' == $active_tab ? ' nav-tab-active' : ''; ?>" <?php echo $hidechild; ?>>
|
22 |
-
<?php _e('@import', 'chld_thm_cfg'); ?>
|
23 |
</a><!----><a id="view_child_options" href=""
|
24 |
class="nav-tab<?php echo 'view_child_options' == $active_tab ? ' nav-tab-active' : ''; ?>" <?php echo $hidechild; ?>>
|
25 |
-
<?php _e('Child CSS', 'chld_thm_cfg'); ?>
|
26 |
</a><!----><a id="view_parnt_options" href=""
|
27 |
class="nav-tab<?php echo 'view_parnt_options' == $active_tab ? ' nav-tab-active' : ''; ?>" <?php echo $hidechild; ?>>
|
28 |
-
<?php _e('Parent CSS', 'chld_thm_cfg'); ?>
|
29 |
</a>
|
30 |
<?php
|
31 |
-
if ('' == $hidechild):
|
32 |
?>
|
33 |
<a id="file_options" href=""
|
34 |
class="nav-tab<?php echo 'file_options' == $active_tab ? ' nav-tab-active' : ''; ?>" <?php echo $hidechild; ?>>
|
35 |
-
<?php _e('Files', 'chld_thm_cfg'); ?>
|
36 |
</a>
|
37 |
<?php
|
38 |
endif;
|
39 |
endif;
|
40 |
-
do_action('chld_thm_cfg_tabs', $this->ctc(), $active_tab, $hidechild); ?>
|
1 |
<?php
|
2 |
+
if ( !defined( 'ABSPATH' ) ) exit;
|
3 |
// Tabs Bar
|
4 |
|
5 |
$active_tab = isset( $_GET[ 'tab' ] ) ? $_GET[ 'tab' ] : 'parent_child_options';
|
8 |
<h2 class="nav-tab-wrapper">
|
9 |
<a id="parent_child_options" href=""
|
10 |
class="nav-tab<?php echo 'parent_child_options' == $active_tab ? ' nav-tab-active' : ''; ?>">
|
11 |
+
<?php _e( 'Parent/Child', 'chld_thm_cfg' ); ?>
|
12 |
</a>
|
13 |
+
<?php if ( $enqueueset ): ?>
|
14 |
<!----><a id="query_selector_options" href=""
|
15 |
class="nav-tab<?php echo 'query_selector_options' == $active_tab ? ' nav-tab-active' : ''; ?>" <?php echo $hidechild; ?>>
|
16 |
+
<?php _e( 'Query/Selector', 'chld_thm_cfg' ); ?>
|
17 |
</a><!----><a id="rule_value_options" href=""
|
18 |
class="nav-tab<?php echo 'rule_value_options' == $active_tab ? ' nav-tab-active' : ''; ?>" <?php echo $hidechild; ?>>
|
19 |
+
<?php _e( 'Rule/Value', 'chld_thm_cfg' ); ?>
|
20 |
</a><!----><a id="import_options" href=""
|
21 |
class="nav-tab<?php echo 'import_options' == $active_tab ? ' nav-tab-active' : ''; ?>" <?php echo $hidechild; ?>>
|
22 |
+
<?php _e( '@import', 'chld_thm_cfg' ); ?>
|
23 |
</a><!----><a id="view_child_options" href=""
|
24 |
class="nav-tab<?php echo 'view_child_options' == $active_tab ? ' nav-tab-active' : ''; ?>" <?php echo $hidechild; ?>>
|
25 |
+
<?php _e( 'Child CSS', 'chld_thm_cfg' ); ?>
|
26 |
</a><!----><a id="view_parnt_options" href=""
|
27 |
class="nav-tab<?php echo 'view_parnt_options' == $active_tab ? ' nav-tab-active' : ''; ?>" <?php echo $hidechild; ?>>
|
28 |
+
<?php _e( 'Parent CSS', 'chld_thm_cfg' ); ?>
|
29 |
</a>
|
30 |
<?php
|
31 |
+
if ( '' == $hidechild ):
|
32 |
?>
|
33 |
<a id="file_options" href=""
|
34 |
class="nav-tab<?php echo 'file_options' == $active_tab ? ' nav-tab-active' : ''; ?>" <?php echo $hidechild; ?>>
|
35 |
+
<?php _e( 'Files', 'chld_thm_cfg' ); ?>
|
36 |
</a>
|
37 |
<?php
|
38 |
endif;
|
39 |
endif;
|
40 |
+
do_action( 'chld_thm_cfg_tabs', $this->ctc(), $active_tab, $hidechild ); ?>
|
includes/forms/themepreview.php
CHANGED
@@ -1,5 +1,5 @@
|
|
1 |
<?php
|
2 |
-
if (!defined('ABSPATH')) exit;
|
3 |
// Theme Preview
|
4 |
// Renders localized version of theme preview that is merged into
|
5 |
// jQuery selectmenu object for parent and child theme options
|
@@ -9,11 +9,15 @@ if (!defined('ABSPATH')) exit;
|
|
9 |
<div class="ctc-theme-option-left"><img src="<?php echo $theme['screenshot']; ?>" class="ctc-theme-option-image"/></div>
|
10 |
<div class="ctc-theme-option-right">
|
11 |
<h3 class="theme-name"><?php echo $theme['Name']; ?></h3>
|
12 |
-
<?php _e('Version: ', 'chld_thm_cfg'); echo esc_attr($theme['Version']);?>
|
13 |
<br/>
|
14 |
-
<?php _e('By: ', 'chld_thm_cfg'); echo esc_attr($theme['Author']);?>
|
15 |
-
<br
|
16 |
-
<a href="<?php echo admin_url('/customize.php?theme=' . $slug);?>" title="<?php _e('
|
17 |
-
|
18 |
-
|
|
|
|
|
|
|
|
|
19 |
</div>
|
1 |
<?php
|
2 |
+
if ( !defined( 'ABSPATH' ) ) exit;
|
3 |
// Theme Preview
|
4 |
// Renders localized version of theme preview that is merged into
|
5 |
// jQuery selectmenu object for parent and child theme options
|
9 |
<div class="ctc-theme-option-left"><img src="<?php echo $theme['screenshot']; ?>" class="ctc-theme-option-image"/></div>
|
10 |
<div class="ctc-theme-option-right">
|
11 |
<h3 class="theme-name"><?php echo $theme['Name']; ?></h3>
|
12 |
+
<?php _e( 'Version: ', 'chld_thm_cfg' ); echo esc_attr( $theme['Version'] );?>
|
13 |
<br/>
|
14 |
+
<?php _e( 'By: ', 'chld_thm_cfg' ); echo esc_attr( $theme['Author'] );?>
|
15 |
+
<br/><?php if ( !is_multisite() || $theme['allowed'] ): ?>
|
16 |
+
<a href="<?php echo admin_url( '/customize.php?theme=' . $slug );?>" title="<?php _e( 'Preview', 'chld_thm_cfg' );
|
17 |
+
if ( is_multisite() ) _e(' in default Site', 'chld_thm_cfg'); ?>" class="ctc-live-preview" target="_blank">
|
18 |
+
<?php _e( 'Live Preview', 'chld_thm_cfg' ); ?>
|
19 |
+
</a><?php else: ?>
|
20 |
+
<a href="<?php echo network_admin_url( '/themes.php?theme=' . $slug );?>" title="<?php _e( 'Go to Themes', 'chld_thm_cfg' ); ?>" class="ctc-live-preview">
|
21 |
+
<?php _e( 'Not Network Enabled', 'chld_thm_cfg' );?>
|
22 |
+
</a><?php endif; ?></div>
|
23 |
</div>
|
includes/help/help_en_US.php
CHANGED
@@ -1,5 +1,5 @@
|
|
1 |
<?php
|
2 |
-
if (!defined('ABSPATH')) exit;
|
3 |
// Help Content
|
4 |
?>
|
5 |
<!-- BEGIN tab -->
|
@@ -93,7 +93,7 @@ if (!defined('ABSPATH')) exit;
|
|
93 |
<li>Click "Live Preview" below the new Child Theme to see it in action.</li>
|
94 |
<li>When you are ready to take the Child Theme live, click "Activate."</li>
|
95 |
</ol>
|
96 |
-
<p>You
|
97 |
<!-- END tab -->
|
98 |
<!-- BEGIN tab -->
|
99 |
<h3 id="ctc_permissions">File Permissions</h3>
|
@@ -142,15 +142,6 @@ if (!defined('ABSPATH')) exit;
|
|
142 |
<h5 id="web_fonts">How do I add Web Fonts?</h5>
|
143 |
<p>The easiest method is to paste the @import code provided by <a href="http://www.google.com/fonts" title="Google Fonts">Google</a>, <a href="http://www.fontsquirrel.com/" title="Font Squirrel">Font Squirrel</a> or any other Web Font site into the @import tab. The fonts will then be available to use as a value of the <strong>font-family</strong> rule. Be sure you understand the license for any embedded fonts. </p>
|
144 |
<p>You can also create a secondary stylesheet that contains @font-face rules and import it using the @import tab. </p>
|
145 |
-
<h5 id="multisite">Does it work with Multi site?</h5>
|
146 |
-
<strong>NOTE: Only users with "edit_theme_options" capability will have access to the Child Theme Configurator.</strong> Using with WordPress Network sites requires additional steps:
|
147 |
-
<ol class="instructions"><li>Install as Network Admin and Network Enable the Plugin.</li>
|
148 |
-
<li>Go to the site you want to customize.</li>
|
149 |
-
<li>Go to Tools > Child Themes and configure a child theme for the parent theme you want to use
|
150 |
-
<li>Go back to Network Admin and Network Enable the new Child theme.</li>
|
151 |
-
<li>Go back the site and activate the child theme.</li></ol>
|
152 |
-
Now you can edit your child theme from Tools > Child Themes. </p>
|
153 |
-
|
154 |
<h5 id="plugin">Does it work with plugins?</h5>
|
155 |
<p>We offer a premium extension to let you easily modify styles for any WordPress Plugin installed on your website. The Child Theme Configurator Plugin Extension scans your plugins and allows you to create custom stylesheets in your Child Theme. <a href="http://www.lilaeamedia.com/plugins/child-theme-plugin-styles/" title="Take Control of your Plugin Styles with Child Theme Configurator Plugin Extension for WordPress">Learn more <i class="genericon genericon-next"></i></a>
|
156 |
<h5 id="doesnt_work">Why doesn't this work with my (insert theme vendor here) theme?</h5>
|
@@ -158,9 +149,6 @@ Now you can edit your child theme from Tools > Child Themes. </p>
|
|
158 |
<p>Contact the vendor directly to ask for this core functionality. It is our opinion that ALL themes (especially commercial ones) must pass the Theme Unit Tests outlined by WordPress.org. </p>
|
159 |
<h5 id="missing_parent">Why doesn't the Parent Theme have any styles when I "View Parent CSS"?</h5>
|
160 |
<p>Your Parent theme is probably using a separate location for the stylesheets. Select individual stylesheets from the "Parse Additional Stylesheets" section of the Parent/Child tab and click "Generate Child Theme Files" again. </p>
|
161 |
-
<h5 id="where_is_it">Where is it in the Admin?</h5>
|
162 |
-
<p><strong>NOTE: Only users with "edit_theme_options" capability will have access to the Child Theme Configurator.</strong> The Child Theme Configurator can be found under the "Tools" menu in the WordPress Admin. Click "Child Themes" to get started.</p>
|
163 |
-
<p>Click the "Help" tab at the top right for a quick reference. </p>
|
164 |
<h5 id="performance">Will this slow down my site?</h5>
|
165 |
Once the child theme stylesheet is created, CTC adds very little overhead to the front-end since all of the functionality is in the admin.
|
166 |
|
1 |
<?php
|
2 |
+
if ( !defined( 'ABSPATH' ) ) exit;
|
3 |
// Help Content
|
4 |
?>
|
5 |
<!-- BEGIN tab -->
|
93 |
<li>Click "Live Preview" below the new Child Theme to see it in action.</li>
|
94 |
<li>When you are ready to take the Child Theme live, click "Activate."</li>
|
95 |
</ol>
|
96 |
+
<p><strong>MULTISITE USERS:</strong> You must Network Enable your child theme before you can use Live Preview. Go to "Themes" in the Network Admin.</p>
|
97 |
<!-- END tab -->
|
98 |
<!-- BEGIN tab -->
|
99 |
<h3 id="ctc_permissions">File Permissions</h3>
|
142 |
<h5 id="web_fonts">How do I add Web Fonts?</h5>
|
143 |
<p>The easiest method is to paste the @import code provided by <a href="http://www.google.com/fonts" title="Google Fonts">Google</a>, <a href="http://www.fontsquirrel.com/" title="Font Squirrel">Font Squirrel</a> or any other Web Font site into the @import tab. The fonts will then be available to use as a value of the <strong>font-family</strong> rule. Be sure you understand the license for any embedded fonts. </p>
|
144 |
<p>You can also create a secondary stylesheet that contains @font-face rules and import it using the @import tab. </p>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
145 |
<h5 id="plugin">Does it work with plugins?</h5>
|
146 |
<p>We offer a premium extension to let you easily modify styles for any WordPress Plugin installed on your website. The Child Theme Configurator Plugin Extension scans your plugins and allows you to create custom stylesheets in your Child Theme. <a href="http://www.lilaeamedia.com/plugins/child-theme-plugin-styles/" title="Take Control of your Plugin Styles with Child Theme Configurator Plugin Extension for WordPress">Learn more <i class="genericon genericon-next"></i></a>
|
147 |
<h5 id="doesnt_work">Why doesn't this work with my (insert theme vendor here) theme?</h5>
|
149 |
<p>Contact the vendor directly to ask for this core functionality. It is our opinion that ALL themes (especially commercial ones) must pass the Theme Unit Tests outlined by WordPress.org. </p>
|
150 |
<h5 id="missing_parent">Why doesn't the Parent Theme have any styles when I "View Parent CSS"?</h5>
|
151 |
<p>Your Parent theme is probably using a separate location for the stylesheets. Select individual stylesheets from the "Parse Additional Stylesheets" section of the Parent/Child tab and click "Generate Child Theme Files" again. </p>
|
|
|
|
|
|
|
152 |
<h5 id="performance">Will this slow down my site?</h5>
|
153 |
Once the child theme stylesheet is created, CTC adds very little overhead to the front-end since all of the functionality is in the admin.
|
154 |
|
js/chld-thm-cfg.js
CHANGED
@@ -2,11 +2,11 @@
|
|
2 |
* Script: chld-thm-cfg.js
|
3 |
* Plugin URI: http://www.lilaeamedia.com/plugins/child-theme-configurator/
|
4 |
* Description: Handles jQuery, AJAX and other UI
|
5 |
-
* Version: 1.6.
|
6 |
* Author: Lilaea Media
|
7 |
* Author URI: http://www.lilaeamedia.com/
|
8 |
* License: GPLv2
|
9 |
-
* Copyright (C) 2014 Lilaea Media
|
10 |
*/
|
11 |
jQuery(document).ready(function($){
|
12 |
|
@@ -874,6 +874,7 @@ jQuery(document).ready(function($){
|
|
874 |
additional;
|
875 |
if (ctc_is_empty(template)) return;
|
876 |
$.get(url, function(data){
|
|
|
877 |
while (additional = regex.exec(data)){
|
878 |
if ('style.css' == additional[1]) break; // bail after main stylesheet
|
879 |
if (additional[1].match(/bootstrap/)) continue; // don't autoselect Bootstrap stylesheets
|
2 |
* Script: chld-thm-cfg.js
|
3 |
* Plugin URI: http://www.lilaeamedia.com/plugins/child-theme-configurator/
|
4 |
* Description: Handles jQuery, AJAX and other UI
|
5 |
+
* Version: 1.6.3
|
6 |
* Author: Lilaea Media
|
7 |
* Author URI: http://www.lilaeamedia.com/
|
8 |
* License: GPLv2
|
9 |
+
* Copyright (C) 2014-2015 Lilaea Media
|
10 |
*/
|
11 |
jQuery(document).ready(function($){
|
12 |
|
874 |
additional;
|
875 |
if (ctc_is_empty(template)) return;
|
876 |
$.get(url, function(data){
|
877 |
+
//console.log(data);
|
878 |
while (additional = regex.exec(data)){
|
879 |
if ('style.css' == additional[1]) break; // bail after main stylesheet
|
880 |
if (additional[1].match(/bootstrap/)) continue; // don't autoselect Bootstrap stylesheets
|
readme.txt
CHANGED
@@ -4,7 +4,7 @@ Donate link: https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_i
|
|
4 |
Tags: child theme, customize, CSS, responsive, css editor, theme generator, stylesheet, customizer
|
5 |
Requires at least: 3.9
|
6 |
Tested up to: 4.1
|
7 |
-
Stable tag: 1.6.
|
8 |
License: GPLv2 or later
|
9 |
License URI: http://www.gnu.org/licenses/gpl-2.0.html
|
10 |
|
@@ -29,16 +29,16 @@ When you are ready, just activate the Child Theme and your WordPress site takes
|
|
29 |
* Update themes without losing customizations
|
30 |
* Easily copy widgets, menus and other options to a child theme
|
31 |
* Save hours of development time
|
|
|
32 |
* Make modifications above and beyond the theme Customizer
|
33 |
* Enqueue (link) parent theme stylesheet instead of using @import
|
34 |
* Export Child Theme as Zip Archive
|
35 |
* Import web fonts and use them in place of theme fonts
|
36 |
* Identify and override exact selectors from the parent theme
|
37 |
* Change specific colors, backgrounds, font styles, etc., without changing other elements
|
38 |
-
* Automatically
|
39 |
-
* Automatically generate cross-browser and vendor-prefixed rules
|
40 |
* Preview style changes before committing to them
|
41 |
-
*
|
42 |
* Uses WP Filesystem API – will not create files you cannot remove
|
43 |
* Nag-free, no-strings-attached user experience
|
44 |
|
@@ -80,6 +80,8 @@ Learn more at http://www.lilaeamedia.com/plugins/intelliwidget-responsive-menu
|
|
80 |
* Browse for the zip file, select and click "Install."
|
81 |
|
82 |
3. In the WordPress Admin, go to "Plugins > Installed Plugins." Locate "Child Theme Configurator" in the list and click "Activate."
|
|
|
|
|
83 |
|
84 |
= 10 Easy Steps to Create a Child Theme =
|
85 |
|
@@ -109,6 +111,20 @@ Learn more at http://www.lilaeamedia.com/plugins/intelliwidget-responsive-menu
|
|
109 |
|
110 |
== Frequently Asked Questions ==
|
111 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
112 |
= HELP! I changed a file and now I am unable to access my website or login to wp-admin to fix it! =
|
113 |
|
114 |
To back out of a broken child theme you have to manually rename the offending theme directory name (via FTP, SSH or your web host control panel file manager) so that WordPress can’t find it. WordPress will then throw an error and revert back to the default theme (currently twenty-fourteen).
|
@@ -144,18 +160,6 @@ The easiest method is to paste the @import code provided by Google, Font Squirre
|
|
144 |
|
145 |
You can also create a secondary stylesheet that contains @font-face rules and import it using the @import tab.
|
146 |
|
147 |
-
= Does it work with Multi site? =
|
148 |
-
|
149 |
-
Using with WordPress Network sites requires additional steps:
|
150 |
-
|
151 |
-
1. Install as Network Admin and Network Enable the Plugin.
|
152 |
-
2. Go to the site you want to customize.
|
153 |
-
3. Go to Tools > Child Themes and configure a child theme for the parent theme you want to use
|
154 |
-
4. Go back to Network Admin and Network Enable the new Child theme.
|
155 |
-
5. Go back the site and activate the child theme.
|
156 |
-
|
157 |
-
Now you can edit your child theme from Tools > Child Themes. NOTE: Only users with "edit_theme_options" capability will have access to the Child Theme Configurator.
|
158 |
-
|
159 |
= Does it work with plugins? =
|
160 |
|
161 |
We offer a premium extension that brings the CSS editing power of Child Theme Configurator to any WordPress Plugin installed on your website. The Child Theme Configurator Plugin Extension scans your plugins and creates custom CSS in your Child Theme. Learn more at http://www.lilaeamedia.com/plugins/child-theme-plugin-styles
|
@@ -182,12 +186,6 @@ Once the child theme stylesheet is created, CTC adds very little overhead to the
|
|
182 |
|
183 |
Check the appropriate additional stylesheets under "Scan Parent Theme for additional stylesheets" on the Parent/Child tab and load the Child Theme again. CTC tries to identify these files by fetching a page from the parent theme, but you may need to set them manually.
|
184 |
|
185 |
-
= Where is it in the Admin? =
|
186 |
-
|
187 |
-
The Child Theme Configurator can be found under the "Tools" menu in the WordPress Admin. Click "Child Themes" to get started. NOTE: Only users with "edit_theme_options" capability will have access to the Child Theme Configurator.
|
188 |
-
|
189 |
-
Click the "Help" tab at the top right for a quick reference.
|
190 |
-
|
191 |
= Where are the styles? The configurator doesn't show anything! =
|
192 |
|
193 |
All of the styles are loaded dynamically. You must start typing in the text boxes to select styles to edit.
|
@@ -207,7 +205,7 @@ You can make any manual changes you wish to the stylesheet. Just make sure you i
|
|
207 |
|
208 |
No. This is the point of using child themes. Changes to the parent theme are automatically inherited by the child theme.
|
209 |
|
210 |
-
A child theme is not a "copy" of the parent theme. It is a special feature of WordPress that let's you override specific styles and functions leaving the rest of the theme intact.
|
211 |
|
212 |
= Where are the .php files? =
|
213 |
|
@@ -261,6 +259,10 @@ https://www.youtube.com/watch?v=iBiiAgsK4G4
|
|
261 |
7. Files tab
|
262 |
|
263 |
== Changelog ==
|
|
|
|
|
|
|
|
|
264 |
|
265 |
= 1.6.2.1 =
|
266 |
* Fix: Regular expression introduced in version 1.6.2 parses selectors incorrectly.
|
@@ -300,7 +302,7 @@ https://www.youtube.com/watch?v=iBiiAgsK4G4
|
|
300 |
* Added regex filter for non-printable (e.g., null) characters in input strings
|
301 |
|
302 |
= 1.5.2.2 =
|
303 |
-
* Fixed a bug introduced in v1.5.2(.1) that copied all of the parent styles to the child stylesheet. This should only be an issue for 'background-image' styles that reference images in the parent theme and do not have child theme overrides.
|
304 |
* Rolled back changes to the javascript controller that introduced a number of type errors.
|
305 |
* Tweaked preview ajax call to handle ssl.
|
306 |
|
@@ -312,12 +314,10 @@ https://www.youtube.com/watch?v=iBiiAgsK4G4
|
|
312 |
* Added copy option to Parent/Child tab to assign menu locations, sidebars/widgets, custom header, background, and other options to the new Child Theme.
|
313 |
|
314 |
= 1.5.0 =
|
315 |
-
*
|
316 |
-
*
|
317 |
-
*
|
318 |
-
* To make things easier we added the ability for you to make the files writable while editing and then make them read-only when you are done.
|
319 |
* You can also set your credentials in wp-config.php: http://codex.wordpress.org/Editing_wp-config.php#WordPress_Upgrade_Constants
|
320 |
-
* Contact us at http://www.lilaeamedia.com/about/contact if you have any questions.
|
321 |
|
322 |
= 1.4.8 =
|
323 |
* Removed backreference in main CSS parser regex due to high memory usage.
|
@@ -442,15 +442,12 @@ https://www.youtube.com/watch?v=iBiiAgsK4G4
|
|
442 |
* Clean up Parent/Child form UI and validation
|
443 |
* Streamlined UI overall
|
444 |
|
445 |
-
= 1.0.1 =
|
446 |
-
* Updates to Readme.txt
|
447 |
-
|
448 |
= 1.0.0 =
|
449 |
* Initial release.
|
450 |
|
451 |
== Upgrade Notice ==
|
452 |
|
453 |
-
v.1.6.
|
454 |
|
455 |
== Override Parent Styles ==
|
456 |
|
@@ -527,9 +524,11 @@ Some themes (particularly commercial themes) do not correctly load parent templa
|
|
527 |
2. Click "Live Preview" (theme customizer) below the new Child Theme to see it in action.
|
528 |
3. When you are ready to take the Child Theme live, click "Activate."
|
529 |
|
|
|
|
|
530 |
== Caveats ==
|
531 |
|
532 |
-
*
|
533 |
* Only two-color gradients. The Child Theme Configurator plugin is powerful, but we have simplified the gradient interface. You can use any gradient you want as long as it has two colors and no intermediate stops.
|
534 |
* No @font-face rules. The Child Theme Configurator plugin only supports @media and @import. If you need other @rules, put them in a separate stylesheet and import them into the Child Theme stylesheet.
|
535 |
* Not all CSS rules are supported. The Child Theme Configurator plugin works with the vast majority of CSS rules, however we’ve left out some of the more obscure options.
|
@@ -539,4 +538,4 @@ Some themes (particularly commercial themes) do not correctly load parent templa
|
|
539 |
|
540 |
Go to http://www.lilaeamedia.com/plugins/child-theme-configurator
|
541 |
|
542 |
-
Copyright: (C) 2014 Lilaea Media
|
4 |
Tags: child theme, customize, CSS, responsive, css editor, theme generator, stylesheet, customizer
|
5 |
Requires at least: 3.9
|
6 |
Tested up to: 4.1
|
7 |
+
Stable tag: 1.6.3
|
8 |
License: GPLv2 or later
|
9 |
License URI: http://www.gnu.org/licenses/gpl-2.0.html
|
10 |
|
29 |
* Update themes without losing customizations
|
30 |
* Easily copy widgets, menus and other options to a child theme
|
31 |
* Save hours of development time
|
32 |
+
* Multisite compatible - great for network sites
|
33 |
* Make modifications above and beyond the theme Customizer
|
34 |
* Enqueue (link) parent theme stylesheet instead of using @import
|
35 |
* Export Child Theme as Zip Archive
|
36 |
* Import web fonts and use them in place of theme fonts
|
37 |
* Identify and override exact selectors from the parent theme
|
38 |
* Change specific colors, backgrounds, font styles, etc., without changing other elements
|
39 |
+
* Automatically generate cross-browser and vendor-prefixed rules and CSS gradients
|
|
|
40 |
* Preview style changes before committing to them
|
41 |
+
* Customize @media queries for responsive design
|
42 |
* Uses WP Filesystem API – will not create files you cannot remove
|
43 |
* Nag-free, no-strings-attached user experience
|
44 |
|
80 |
* Browse for the zip file, select and click "Install."
|
81 |
|
82 |
3. In the WordPress Admin, go to "Plugins > Installed Plugins." Locate "Child Theme Configurator" in the list and click "Activate."
|
83 |
+
|
84 |
+
4. Navigate to Tools > Child Themes (multisite users go to Network Admin > Themes > Child Themes).
|
85 |
|
86 |
= 10 Easy Steps to Create a Child Theme =
|
87 |
|
111 |
|
112 |
== Frequently Asked Questions ==
|
113 |
|
114 |
+
= Where is Child Theme Configurator in the Admin? =
|
115 |
+
|
116 |
+
For most users the Child Theme Configurator can be found under "Tools > Child Themes."
|
117 |
+
|
118 |
+
WordPress Multisite (Network) users go to "Network Admin > Themes > Child Themes."
|
119 |
+
|
120 |
+
NOTE: Only users with "install_themes" capability will have access to the Child Theme Configurator.
|
121 |
+
|
122 |
+
Click the "Help" tab at the top right for a quick reference.
|
123 |
+
|
124 |
+
= Does it work with Multisite? =
|
125 |
+
|
126 |
+
Yes. Go to "Network Admin > Themes > Child Themes." Child themes must be "Network enabled" to preview and activate for Network sites.
|
127 |
+
|
128 |
= HELP! I changed a file and now I am unable to access my website or login to wp-admin to fix it! =
|
129 |
|
130 |
To back out of a broken child theme you have to manually rename the offending theme directory name (via FTP, SSH or your web host control panel file manager) so that WordPress can’t find it. WordPress will then throw an error and revert back to the default theme (currently twenty-fourteen).
|
160 |
|
161 |
You can also create a secondary stylesheet that contains @font-face rules and import it using the @import tab.
|
162 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
163 |
= Does it work with plugins? =
|
164 |
|
165 |
We offer a premium extension that brings the CSS editing power of Child Theme Configurator to any WordPress Plugin installed on your website. The Child Theme Configurator Plugin Extension scans your plugins and creates custom CSS in your Child Theme. Learn more at http://www.lilaeamedia.com/plugins/child-theme-plugin-styles
|
186 |
|
187 |
Check the appropriate additional stylesheets under "Scan Parent Theme for additional stylesheets" on the Parent/Child tab and load the Child Theme again. CTC tries to identify these files by fetching a page from the parent theme, but you may need to set them manually.
|
188 |
|
|
|
|
|
|
|
|
|
|
|
|
|
189 |
= Where are the styles? The configurator doesn't show anything! =
|
190 |
|
191 |
All of the styles are loaded dynamically. You must start typing in the text boxes to select styles to edit.
|
205 |
|
206 |
No. This is the point of using child themes. Changes to the parent theme are automatically inherited by the child theme.
|
207 |
|
208 |
+
A child theme is not a "copy" of the parent theme. It is a special feature of WordPress that let's you override specific styles and functions leaving the rest of the theme intact. Quality themes should identify any deprecated functions or styles in the upgrade notes so that child theme users can make adjustments accordingly.
|
209 |
|
210 |
= Where are the .php files? =
|
211 |
|
259 |
7. Files tab
|
260 |
|
261 |
== Changelog ==
|
262 |
+
= 1.6.3 =
|
263 |
+
* New Feature: Better child theme handling for multisite. Moved interface to Themes menu and check for network enabled.
|
264 |
+
* Fix: Restrict child theme configurator access to install_themes capability
|
265 |
+
* Fix: Preview links to Themes admin if not network enabled to prevent 'Cheatin, uh?' error.
|
266 |
|
267 |
= 1.6.2.1 =
|
268 |
* Fix: Regular expression introduced in version 1.6.2 parses selectors incorrectly.
|
302 |
* Added regex filter for non-printable (e.g., null) characters in input strings
|
303 |
|
304 |
= 1.5.2.2 =
|
305 |
+
* Fixed a bug introduced in v1.5.2(.1) that copied all of the parent styles to the child stylesheet. This should only be an issue for 'background-image' styles that reference images in the parent theme and do not have child theme overrides.
|
306 |
* Rolled back changes to the javascript controller that introduced a number of type errors.
|
307 |
* Tweaked preview ajax call to handle ssl.
|
308 |
|
314 |
* Added copy option to Parent/Child tab to assign menu locations, sidebars/widgets, custom header, background, and other options to the new Child Theme.
|
315 |
|
316 |
= 1.5.0 =
|
317 |
+
* Refactored CTC to use the WP_Filesystem API.
|
318 |
+
* Non suExec configurations will now require user credentials to add, remove or update Child Theme files.
|
319 |
+
* Added the ability for you to make the files writable while editing and then make them read-only when you are done.
|
|
|
320 |
* You can also set your credentials in wp-config.php: http://codex.wordpress.org/Editing_wp-config.php#WordPress_Upgrade_Constants
|
|
|
321 |
|
322 |
= 1.4.8 =
|
323 |
* Removed backreference in main CSS parser regex due to high memory usage.
|
442 |
* Clean up Parent/Child form UI and validation
|
443 |
* Streamlined UI overall
|
444 |
|
|
|
|
|
|
|
445 |
= 1.0.0 =
|
446 |
* Initial release.
|
447 |
|
448 |
== Upgrade Notice ==
|
449 |
|
450 |
+
v.1.6.3 **IMPORTANT:** As of v.1.6.3, only users with "install_themes" capability have access to the Child Theme Configurator. This resolves permission issues with both multisite and single site installs. **MULTISITE USERS:** The Admin HAS MOVED to Network Admin > Themes > Child Themes for better handling for multisite (network) installs. See changelog for details.
|
451 |
|
452 |
== Override Parent Styles ==
|
453 |
|
524 |
2. Click "Live Preview" (theme customizer) below the new Child Theme to see it in action.
|
525 |
3. When you are ready to take the Child Theme live, click "Activate."
|
526 |
|
527 |
+
**MULTISITE USERS:** You must Network Enable your child theme before you can use Live Preview. Go to "Themes" in the Network Admin.
|
528 |
+
|
529 |
== Caveats ==
|
530 |
|
531 |
+
* The Child Theme Configurator plugin does not support the legacy webkit gradient.
|
532 |
* Only two-color gradients. The Child Theme Configurator plugin is powerful, but we have simplified the gradient interface. You can use any gradient you want as long as it has two colors and no intermediate stops.
|
533 |
* No @font-face rules. The Child Theme Configurator plugin only supports @media and @import. If you need other @rules, put them in a separate stylesheet and import them into the Child Theme stylesheet.
|
534 |
* Not all CSS rules are supported. The Child Theme Configurator plugin works with the vast majority of CSS rules, however we’ve left out some of the more obscure options.
|
538 |
|
539 |
Go to http://www.lilaeamedia.com/plugins/child-theme-configurator
|
540 |
|
541 |
+
Copyright: (C) 2014-2015 Lilaea Media
|