Multiple Themes - Version 7.1

Version Description

  • Very Simple AJAX Support: select a theme whenever /wp-admin/admin-ajax.php is accessed by URL
  • Remove P2 Theme automatic handling as it no longer works with current version of P2 Theme
Download this release

Release Info

Developer dgewirtz
Plugin Icon 128x128 Multiple Themes
Version 7.1
Comparing to
See all releases

Code changes from version 4.0.2 to 7.1

includes/admin-functions.php ADDED
@@ -0,0 +1,303 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /* Exit if .php file accessed directly
4
+ */
5
+ if ( !defined( 'ABSPATH' ) ) {
6
+ exit;
7
+ }
8
+
9
+ function jr_mt_messages( $message, $action = 'count' ) {
10
+ global $jr_mt_messages;
11
+ switch ( $action ) {
12
+ case 'display':
13
+ if ( isset( $jr_mt_messages ) ) {
14
+ foreach ( $jr_mt_messages as $echo => $count ) {
15
+ echo '<li>' . $echo;
16
+ if ( $count > 1 ) {
17
+ echo ' ('. $count . ' times)';
18
+ }
19
+ echo '</li>';
20
+ }
21
+ unset( $jr_mt_messages );
22
+ }
23
+ if ( empty( $message ) ) {
24
+ break;
25
+ }
26
+ /* Purposely let it fall through to output message,
27
+ after stored messages are output.
28
+ */
29
+ case 'immediate':
30
+ echo '<li>' . $message . '</li>';
31
+ break;
32
+ case 'count':
33
+ if ( isset( $jr_mt_messages[ $message ] ) ) {
34
+ ++$jr_mt_messages[ $message ];
35
+ } else {
36
+ $jr_mt_messages[ $message ] = 1;
37
+ }
38
+ break;
39
+ }
40
+ }
41
+
42
+ function jr_mt_theme_entry( $type, $theme = '', $display1 = NULL, $display2 = NULL ) {
43
+ $three_dots = '&#133;';
44
+ $before = '<li>Delete <input type="checkbox" id="del_entry" name="jr_mt_settings[del_entry][]" value="';
45
+ $after = '" /> &nbsp; ';
46
+ /* Fortunately, wp_get_theme() creates an Object if $theme does not exist,
47
+ complete with a Name entry that matches the folder name.
48
+
49
+ TODO: flag the situation of a non-existent Theme (i.e. - was deleted after entry was created)
50
+ */
51
+ $theme_equals = 'Theme=' . wp_get_theme( $theme )->Name . '; ';
52
+ switch ( $type ) {
53
+ case 'Query':
54
+ echo $before
55
+ . 'query'
56
+ . '='
57
+ . $display1
58
+ . '='
59
+ . $display2
60
+ . $after
61
+ . $theme_equals;
62
+ if ( '*' !== $display2 ) {
63
+ $settings = get_option( 'jr_mt_settings' );
64
+ $sticky = isset( $settings['remember']['query'][ $display1 ][ $display2 ] );
65
+ $override = isset( $settings['override']['query'][ $display1 ][ $display2 ] );
66
+ if ( $sticky ) {
67
+ if ( $override ) {
68
+ echo 'Sticky/Override ';
69
+ } else {
70
+ echo 'Sticky ';
71
+ }
72
+ } else {
73
+ if ( $override ) {
74
+ echo 'Override ';
75
+ }
76
+ }
77
+ }
78
+ echo 'Query='
79
+ . '<code>'
80
+ . JR_MT_HOME_URL
81
+ . "/</code>$three_dots<code>/?"
82
+ . '<b><input type="text" readonly="readonly" disable="disabled" name="jr_mt_delkw" value="'
83
+ . $display1
84
+ . '" size="'
85
+ . jr_mt_strlen( $display1 )
86
+ . '" /></b>'
87
+ . '=';
88
+ if ( '*' === $display2 ) {
89
+ echo '</code>' . $three_dots;
90
+ } else {
91
+ echo '<b><input type="text" readonly="readonly" disable="disabled" name="jr_mt_delkwval" value="'
92
+ . $display2
93
+ . '" size="'
94
+ . jr_mt_strlen( $display2 )
95
+ . '" /></b></code>';
96
+ }
97
+ break;
98
+ case 'url':
99
+ case 'url_prefix':
100
+ case 'url_asterisk':
101
+ echo $before
102
+ . $type
103
+ . '='
104
+ . 'url'
105
+ . '='
106
+ . $display1
107
+ . $after
108
+ . $theme_equals
109
+ . $display2
110
+ . '=<code>' . $display1 . '</code>';
111
+ break;
112
+ case 'wordpress':
113
+ echo '<li><a href="'
114
+ . get_admin_url()
115
+ . 'themes.php" class="button-primary">Change</a> &nbsp; '
116
+ . 'Theme='
117
+ . wp_get_theme()->Name
118
+ . ', the Theme chosen as Active from Appearance-Themes in the WordPress Admin panels';
119
+ break;
120
+ default:
121
+ echo $before
122
+ . $type
123
+ . $after
124
+ . $theme_equals
125
+ . $display1;
126
+ if ( 'site_home' === $type ) {
127
+ echo ' (<code>' . JR_MT_HOME_URL . '</code>) setting';
128
+ } else {
129
+ echo ' setting (see Advanced Settings tab)';
130
+ }
131
+ break;
132
+ }
133
+ echo '</li>';
134
+ }
135
+
136
+ // $theme_name is the name of the Theme's folder within the Theme directory
137
+ function jr_mt_themes_field( $field_name, $theme_name, $setting, $excl_current_theme ) {
138
+ echo "<select id='$field_name' name='$setting" . "[$field_name]' size='1'>";
139
+ if ( empty( $theme_name ) ) {
140
+ $selected = 'selected="selected"';
141
+ } else {
142
+ $selected = '';
143
+ }
144
+ echo "<option value='' $selected></option>";
145
+ foreach ( jr_mt_all_themes() as $folder => $theme_obj ) {
146
+ if ( $excl_current_theme ) {
147
+ if ( ( jr_mt_current_theme( 'stylesheet' ) == $theme_obj['stylesheet'] ) && ( jr_mt_current_theme( 'template' ) == $theme_obj['template'] ) ) {
148
+ // Skip the Current Theme
149
+ continue;
150
+ }
151
+ }
152
+ if ( $theme_name === $folder ) {
153
+ $selected = 'selected="selected"';
154
+ } else {
155
+ $selected = '';
156
+ }
157
+ $name = $theme_obj->Name;
158
+ echo "<option value='$folder' $selected>$name</option>";
159
+ }
160
+ echo '</select>' . PHP_EOL;
161
+ }
162
+
163
+ /**
164
+ * Update available for Plugin?
165
+ *
166
+ * @return bool - TRUE if an update is available in the WordPress Repository,
167
+ * FALSE if no update is available or if the update_plugins transient is not available
168
+ * (which also results in an error message).
169
+ **/
170
+ function jr_mt_plugin_update_available() {
171
+ global $jr_mt_update_plugins;
172
+ if ( !isset( $jr_mt_update_plugins ) ) {
173
+ $transient = get_site_transient( 'update_plugins' );
174
+ if ( FALSE === $transient ) {
175
+ // Error
176
+ return FALSE;
177
+ } else {
178
+ $jr_mt_update_plugins = $transient;
179
+ }
180
+ }
181
+ if ( empty( $jr_mt_update_plugins->response ) ) {
182
+ return FALSE;
183
+ }
184
+ return array_key_exists( jr_mt_plugin_basename(), $jr_mt_update_plugins->response );
185
+ }
186
+
187
+ /**
188
+ * Prepare URL Query Value
189
+ *
190
+ * Sanitize and standardize a URL Query Value for storage in a database.
191
+ * Does not support ?keyword[]=value, i.e. - $value cannot be an Array.
192
+ *
193
+ * @param string $value URL Query Value to be sanitized and standardized; will fail if array
194
+ * @return string URL Query Value after being sanitized and standardized
195
+ */
196
+ function jr_mt_prep_query_value( $value ) {
197
+ return str_ireplace( '%e2%80%8e', '', jr_mt_strtolower( trim( $value ) ) );
198
+ }
199
+ function jr_mt_prep_query_keyword( $keyword ) {
200
+ return jr_mt_prep_query_value( $keyword );
201
+ }
202
+
203
+ /**
204
+ * Sanitize a URL from a Text Form field intended for database storage
205
+ */
206
+ function jr_mt_sanitize_url( $url ) {
207
+ /* Handle troublesome %E2%80%8E UTF Left-to-right Mark (LRM) suffix first.
208
+ */
209
+ if ( FALSE === stripos( $url, '%E2%80%8E' ) ) {
210
+ if ( FALSE === stripos( rawurlencode( $url ), '%E2%80%8E' ) ) {
211
+ $clean_url = $url;
212
+ } else {
213
+ $clean_url = rawurldecode( str_ireplace( '%E2%80%8E', '', rawurlencode( $url ) ) );
214
+ }
215
+ } else {
216
+ $clean_url = str_ireplace( '%E2%80%8E', '', $url );
217
+ }
218
+ $clean_url = rawurldecode( trim( $clean_url ) );
219
+
220
+ return $clean_url;
221
+ }
222
+
223
+ /**
224
+ * Make URL Relative to Site URL
225
+ *
226
+ */
227
+ function jr_mt_relative_url( $url, $site_url ) {
228
+ $url_path_array = parse_url( $url );
229
+ $url_path = $url_path_array['path'];
230
+ if ( !empty( $url_path_array['query'] ) ) {
231
+ $url_path .= '?' . $url_path_array['query'];
232
+ }
233
+ $site_url_path = parse_url( $site_url, PHP_URL_PATH );
234
+ return trim( jr_mt_substr( $url_path, jr_mt_strlen( $site_url_path ) ), '/\\' );
235
+ }
236
+
237
+ function jr_mt_missing_rel_url( $settings, $relative_to_url ) {
238
+ global $jr_mt_url_types;
239
+ foreach ( $jr_mt_url_types as $url_type ) {
240
+ if ( isset( $settings[ $url_type ] ) && is_array( $settings[ $url_type ] ) ) {
241
+ foreach ( $settings[ $url_type ] as $index => $url_array ) {
242
+ if ( !isset( $url_array['rel_url'] ) ) {
243
+ $settings[ $url_type ][ $index ]['rel_url'] = jr_mt_relative_url( $url_array['url'], $relative_to_url );
244
+ jr_mt_messages( 'Missing Relative URL added to URL setting' );
245
+ }
246
+ }
247
+ }
248
+ }
249
+ return $settings;
250
+ }
251
+
252
+ function jr_mt_rebuild_display_url( $settings, $old_site_url ) {
253
+ global $jr_mt_url_types;
254
+ foreach ( $jr_mt_url_types as $url_type ) {
255
+ if ( isset( $settings[ $url_type ] ) && is_array( $settings[ $url_type ] ) ) {
256
+ foreach ( $settings[ $url_type ] as $index => $url_array ) {
257
+ if ( !isset( $url_array['rel_url'] ) ) {
258
+ $settings[ $url_type ][ $index ]['rel_url'] = jr_mt_relative_url( $url_array['url'], $old_site_url );
259
+ }
260
+ $settings[ $url_type ][ $index ]['url'] = JR_MT_HOME_URL . '/' . $settings[ $url_type ][ $index ]['rel_url'];
261
+ }
262
+ } else {
263
+ $settings[ $url_type ] = array();
264
+ }
265
+ }
266
+ return $settings;
267
+ }
268
+
269
+ function jr_mt_rebuild_alias_home( $settings ) {
270
+ /* See if there is an Alias entry for the new Site URL.
271
+ If not, add one, and perhaps another with/without www.
272
+ */
273
+ $no_home = TRUE;
274
+ foreach ( $settings['aliases'] as $index => $alias ) {
275
+ if ( $settings['aliases'][ $index ]['home'] = jr_mt_same_url( $alias['prep'], JR_MT_HOME_URL ) ) {
276
+ $no_home = FALSE;
277
+ }
278
+ }
279
+ if ( $no_home ) {
280
+ $settings['aliases'] = array_merge( $settings['aliases'], jr_mt_init_aliases() );
281
+ }
282
+ return $settings;
283
+ }
284
+
285
+ function jr_mt_rebuild_prep( $settings ) {
286
+ /* Assumes that ['url'*] and ['aliases'] Settings have been checked,
287
+ so doesn't check if they exist and are array.
288
+ Be sure to do that if wrappering this function with get_ and update_option().
289
+ */
290
+ global $jr_mt_url_types;
291
+ foreach ( $jr_mt_url_types as $url_type ) {
292
+ foreach ( $settings[ $url_type ] as $url_key => $url_array ) {
293
+ $settings[ $url_type ][ $url_key ]['prep'] = array();
294
+ $rel_url = $url_array['rel_url'];
295
+ foreach ( $settings['aliases'] as $index => $alias ) {
296
+ $settings[ $url_type ][ $url_key ]['prep'][ $index ] = jr_mt_prep_url( $alias['url'] . '/' . $rel_url );
297
+ }
298
+ }
299
+ }
300
+ return $settings;
301
+ }
302
+
303
+ ?>
includes/admin-sections.php ADDED
@@ -0,0 +1,870 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /* Exit if .php file accessed directly
4
+ */
5
+ if ( !defined( 'ABSPATH' ) ) {
6
+ exit;
7
+ }
8
+
9
+ /**
10
+ * Define the settings
11
+ *
12
+ * Everything to be stored and/or can be set by the user
13
+ *
14
+ */
15
+ function jr_mt_admin_init() {
16
+ $settings = get_option( 'jr_mt_settings' );
17
+ foreach ( array( 'query', 'url', 'url_prefix', 'url_asterisk' ) as $key ) {
18
+ if ( !empty( $settings[ $key ] ) ) {
19
+ DEFINE( 'JR_MT_LIST_SETTINGS', TRUE );
20
+ break;
21
+ }
22
+ }
23
+ if ( defined( 'JR_MT_LIST_SETTINGS' ) ) {
24
+ add_settings_section(
25
+ 'jr_mt_delete_settings_section',
26
+ 'Current Theme Selection Entries',
27
+ 'jr_mt_delete_settings_expl',
28
+ 'jr_mt_settings_page'
29
+ );
30
+ add_settings_field(
31
+ 'del_entry',
32
+ 'Theme Selection Entries:',
33
+ 'jr_mt_echo_delete_entry',
34
+ 'jr_mt_settings_page',
35
+ 'jr_mt_delete_settings_section'
36
+ );
37
+ }
38
+ add_settings_section(
39
+ 'jr_mt_site_home_section',
40
+ '<input name="jr_mt_settings[tab1]" type="submit" value="Save All Changes" class="button-primary" /></h3><h3>Site Home',
41
+ 'jr_mt_site_home_expl',
42
+ 'jr_mt_settings_page'
43
+ );
44
+ add_settings_field(
45
+ 'site_home',
46
+ 'Select Theme for Site Home<br /><code>' . JR_MT_HOME_URL . '</code>',
47
+ 'jr_mt_echo_site_home',
48
+ 'jr_mt_settings_page',
49
+ 'jr_mt_site_home_section'
50
+ );
51
+ add_settings_section(
52
+ 'jr_mt_single_settings_section',
53
+ 'For An Individual Page, Post or other non-Admin page;<br />or a group of pages, specified by URL Prefix, optionally with Asterisk(s)',
54
+ 'jr_mt_single_settings_expl',
55
+ 'jr_mt_settings_page'
56
+ );
57
+ add_settings_field( 'add_is_prefix', 'Select here if URL is a Prefix', 'jr_mt_echo_add_is_prefix', 'jr_mt_settings_page', 'jr_mt_single_settings_section' );
58
+ add_settings_field( 'add_theme', 'Theme', 'jr_mt_echo_add_theme', 'jr_mt_settings_page', 'jr_mt_single_settings_section' );
59
+ add_settings_field( 'add_path_id', 'URL of Page, Post, Prefix or other', 'jr_mt_echo_add_path_id', 'jr_mt_settings_page', 'jr_mt_single_settings_section' );
60
+ add_settings_section( 'jr_mt_querykw_section',
61
+ 'For A Query Keyword on any Page, Post or other non-Admin page',
62
+ 'jr_mt_querykw_expl',
63
+ 'jr_mt_settings_page'
64
+ );
65
+ add_settings_field( 'add_querykw_theme', 'Theme', 'jr_mt_echo_add_querykw_theme', 'jr_mt_settings_page', 'jr_mt_querykw_section' );
66
+ add_settings_field( 'add_querykw_keyword', 'Query Keyword', 'jr_mt_echo_add_querykw_keyword', 'jr_mt_settings_page', 'jr_mt_querykw_section' );
67
+ add_settings_section( 'jr_mt_query_section',
68
+ 'For A Query Keyword=Value on any Page, Post or other non-Admin page',
69
+ 'jr_mt_query_expl',
70
+ 'jr_mt_settings_page'
71
+ );
72
+ add_settings_field( 'add_query_theme', 'Theme', 'jr_mt_echo_add_query_theme', 'jr_mt_settings_page', 'jr_mt_query_section' );
73
+ add_settings_field( 'add_query_keyword', 'Query Keyword', 'jr_mt_echo_add_query_keyword', 'jr_mt_settings_page', 'jr_mt_query_section' );
74
+ add_settings_field( 'add_query_value', 'Query Value', 'jr_mt_echo_add_query_value', 'jr_mt_settings_page', 'jr_mt_query_section' );
75
+ add_settings_section( 'jr_mt_aliases_section',
76
+ '<input name="jr_mt_settings[tab1]" type="submit" value="Save All Changes" class="button-primary" /></h3></div><div id="jr-mt-settings2" style="display: none;"><h3>Site Aliases used in URLs to Access This WordPress Site',
77
+ 'jr_mt_aliases_expl',
78
+ 'jr_mt_settings_page'
79
+ );
80
+ /* There is always an entry for the Site URL ("Home").
81
+ */
82
+ if ( count( $settings['aliases'] ) > 1 ) {
83
+ add_settings_section(
84
+ 'jr_mt_delete_aliases_section',
85
+ 'Current Site Alias Entries',
86
+ 'jr_mt_delete_aliases_expl',
87
+ 'jr_mt_settings_page'
88
+ );
89
+ add_settings_field(
90
+ 'del_alias_entry',
91
+ 'Site Alias Entries:',
92
+ 'jr_mt_echo_delete_alias_entry',
93
+ 'jr_mt_settings_page',
94
+ 'jr_mt_delete_aliases_section'
95
+ );
96
+ }
97
+ add_settings_section(
98
+ 'jr_mt_create_alias_section',
99
+ 'Create New Site Alias Entry',
100
+ 'jr_mt_create_alias_expl',
101
+ 'jr_mt_settings_page'
102
+ );
103
+ add_settings_field(
104
+ 'add_alias',
105
+ 'Site Alias',
106
+ 'jr_mt_echo_add_alias',
107
+ 'jr_mt_settings_page',
108
+ 'jr_mt_create_alias_section'
109
+ );
110
+ add_settings_section( 'jr_mt_sticky_section',
111
+ '<input name="jr_mt_settings[tab2]" type="submit" value="Save All Changes" class="button-primary" /></h3></div><div id="jr-mt-settings3" style="display: none;"><h3>Advanced Settings</h3><p><b>Warning:</b> As the name of this section implies, Advanced Settings should be fully understood or they may surprise you with unintended consequences, so please be careful.</p><h3>Sticky and Override',
112
+ 'jr_mt_sticky_expl',
113
+ 'jr_mt_settings_page'
114
+ );
115
+ add_settings_field( 'query_present', 'When to add Sticky Query to a URL', 'jr_mt_echo_query_present', 'jr_mt_settings_page', 'jr_mt_sticky_section' );
116
+ add_settings_field( 'sticky_query', 'Keyword=Value Entries:', 'jr_mt_echo_sticky_query_entry', 'jr_mt_settings_page', 'jr_mt_sticky_section' );
117
+ add_settings_section( 'jr_mt_everything_section',
118
+ 'Theme for Everything',
119
+ 'jr_mt_everything_expl',
120
+ 'jr_mt_settings_page'
121
+ );
122
+ add_settings_field( 'current',
123
+ 'Select Theme for Everything, to Override WordPress Current Theme (<b>' . wp_get_theme()->Name . '</b>)',
124
+ 'jr_mt_echo_current',
125
+ 'jr_mt_settings_page',
126
+ 'jr_mt_everything_section'
127
+ );
128
+ add_settings_section( 'jr_mt_all_settings_section',
129
+ 'For All Pages and/or All Posts',
130
+ 'jr_mt_all_settings_expl',
131
+ 'jr_mt_settings_page'
132
+ );
133
+ $suffix = array(
134
+ 'Pages' => '<br />(Pages created with Add Page)',
135
+ 'Posts' => ''
136
+ );
137
+ foreach ( array( 'Pages', 'Posts' ) as $thing ) {
138
+ add_settings_field( 'all_' . jr_mt_strtolower( $thing ), "Select Theme for All $thing" . $suffix[$thing], 'jr_mt_echo_all_things', 'jr_mt_settings_page', 'jr_mt_all_settings_section',
139
+ array( 'thing' => $thing ) );
140
+ }
141
+ add_settings_section( 'jr_mt_ajax_section',
142
+ 'AJAX',
143
+ 'jr_mt_ajax_expl',
144
+ 'jr_mt_settings_page'
145
+ );
146
+ add_settings_field( 'ajax_all',
147
+ 'Theme for <code>admin-ajax.php</code>',
148
+ 'jr_mt_echo_ajax_all',
149
+ 'jr_mt_settings_page',
150
+ 'jr_mt_ajax_section'
151
+ );
152
+ }
153
+
154
+ /**
155
+ * Section text for Section1
156
+ *
157
+ * Display an explanation of this Section
158
+ *
159
+ */
160
+ function jr_mt_delete_settings_expl() {
161
+ if ( defined( 'JR_MT_LIST_SETTINGS' ) ) {
162
+ ?>
163
+ <p>
164
+ All Theme Selection entries are displayed below,
165
+ in the exact order in which they will be processed.
166
+ For example,
167
+ if a match is made with the first Entry,
168
+ the first Entry's Theme will be used,
169
+ no matter what Theme the Second and subsequent Entries specify.
170
+ </p>
171
+ <p>
172
+ You can delete any of these entries by filling in the check box beside the entry
173
+ and clicking any of the <b>Save All Changes</b> buttons.
174
+ To change the Theme for an entry,
175
+ you will need to delete the entry
176
+ and add the same entry with a different Theme in the relevant section
177
+ on this or the Advanced Settings tab.
178
+ </p>
179
+ <p>
180
+ To add or remove (or to learn about) the Sticky or Override setting for a Query,
181
+ see the Advanced Settings tab.
182
+ </p>
183
+ <?php
184
+ }
185
+ }
186
+
187
+ function jr_mt_echo_delete_entry() {
188
+ echo 'In order of Selection:<ol>';
189
+ $settings = get_option( 'jr_mt_settings' );
190
+ /* Display any Override entries first,
191
+ because they have the highest priority.
192
+ */
193
+ foreach ( $settings['override']['query'] as $override_keyword => $override_value_array ) {
194
+ foreach ( $override_value_array as $override_value => $bool ) {
195
+ jr_mt_theme_entry(
196
+ 'Query',
197
+ wp_get_theme( $settings['query'][ $override_keyword ][ $override_value ] )->Name,
198
+ $override_keyword,
199
+ $override_value
200
+ );
201
+ }
202
+ }
203
+ /* Display Non-Overrides:
204
+ first, keyword=value query in URL with matching setting entry.
205
+ */
206
+ foreach ( $settings['query'] as $keyword => $value_array ) {
207
+ foreach ( $value_array as $value => $theme ) {
208
+ /* Wildcard Keyword=* entries come later
209
+ */
210
+ if ( '*' !== $value ) {
211
+ if ( !isset( $settings['override']['query'][ $keyword ][ $value ] ) ) {
212
+ jr_mt_theme_entry(
213
+ 'Query',
214
+ wp_get_theme( $theme )->Name,
215
+ $keyword,
216
+ $value
217
+ );
218
+ }
219
+ }
220
+ }
221
+ }
222
+ /* Display Non-Overrides:
223
+ second, wildcard keyword=* query in URL with matching setting entry.
224
+ */
225
+ foreach ( $settings['query'] as $keyword => $value_array ) {
226
+ foreach ( $value_array as $value => $theme ) {
227
+ /* Wildcard Keyword=* entries
228
+ Overrides are not allowed, so no need to check.
229
+ */
230
+ if ( '*' === $value ) {
231
+ jr_mt_theme_entry(
232
+ 'Query',
233
+ wp_get_theme( $theme )->Name,
234
+ $keyword,
235
+ '*'
236
+ );
237
+ }
238
+ }
239
+ }
240
+ /* Display URL entries:
241
+ first, exact match URL entries;
242
+ second, prefix URL entries;
243
+ then, prefix URL entries with asterisk wildcards.
244
+ */
245
+ foreach ( array(
246
+ 'url' => 'URL',
247
+ 'url_prefix' => 'URL Prefix',
248
+ 'url_asterisk' => 'URL Prefix*'
249
+ ) as $key => $description ) {
250
+ foreach ( $settings[ $key ] as $settings_array ) {
251
+ jr_mt_theme_entry(
252
+ $key,
253
+ wp_get_theme( $settings_array['theme'] )->Name,
254
+ $settings_array['url'],
255
+ $description
256
+ );
257
+ }
258
+ }
259
+ /* Home Entry, then All Posts and Pages, and Everything Else
260
+ */
261
+ foreach ( array(
262
+ 'ajax_all' => 'AJAX',
263
+ 'site_home' => 'Home',
264
+ 'all_posts' => 'All Posts',
265
+ 'all_pages' => 'All Pages',
266
+ 'current' => 'Everything Else'
267
+ ) as $key => $description ) {
268
+ if ( '' !== $settings[ $key ] ) {
269
+ jr_mt_theme_entry(
270
+ $key,
271
+ wp_get_theme( $settings[ $key ] )->Name,
272
+ $description
273
+ );
274
+ }
275
+ }
276
+ if ( '' === $settings['current'] ) {
277
+ jr_mt_theme_entry(
278
+ 'wordpress'
279
+ );
280
+ }
281
+ echo '</ol>';
282
+ }
283
+
284
+ /**
285
+ * Section text for Section2
286
+ *
287
+ * Display an explanation of this Section
288
+ *
289
+ */
290
+ function jr_mt_site_home_expl() {
291
+ ?>
292
+ <p>
293
+ In this section, you can select a different Theme for Site Home.
294
+ To remove a previously selected Theme, select the blank entry from the drop-down list.
295
+ </p>
296
+ <p>
297
+ In the <i>next</i> section, you will be able to select a Theme, including the Current Theme, for individual Pages, Posts or
298
+ any other non-Admin pages that have their own Permalink; for example, specific Archive or Category pages.
299
+ Or groups of Pages, Posts or any other non-Admin pages that share the same URL Prefix.
300
+ </p>
301
+ <p>
302
+ There is also a Query Keyword section
303
+ farther down this Settings page
304
+ that allows
305
+ you to select a Theme to use whenever a specified
306
+ Query Keyword (<code>?keyword=value</code> or <code>&keyword=value</code>)
307
+ appears in the URL of any Page, Post or other non-Admin page.
308
+ Query entries will even override the Site Home entry,
309
+ if the Query Keyword follows the Site Home URL.
310
+ </p>
311
+ <?php
312
+ }
313
+
314
+ function jr_mt_echo_site_home() {
315
+ $settings = get_option( 'jr_mt_settings' );
316
+ jr_mt_themes_field( 'site_home', $settings['site_home'], 'jr_mt_settings', FALSE );
317
+ }
318
+
319
+ /**
320
+ * Section text for Section3
321
+ *
322
+ * Display an explanation of this Section
323
+ *
324
+ */
325
+ function jr_mt_single_settings_expl() {
326
+ ?>
327
+ <p>
328
+ Select a Theme for an individual Page, Post or
329
+ any other non-Admin page that has its own Permalink; for example, a specific Archive or Category page.
330
+ Or for a group of pages which have URLs that all begin with the same characters ("Prefix"),
331
+ optionally specifying an Asterisk ("*") to match all subdirectories at specific levels.
332
+ </p>
333
+ <p>
334
+ Then cut and paste the URL of the desired Page, Post, Prefix or other non-Admin page.
335
+ And click any of the <b>Save All Changes</b> buttons to add the entry.
336
+ </p>
337
+ There are three types of Entries that you can specify here:
338
+ <ol>
339
+ <li>
340
+ <b>URL</b> - if Visitor URL matches this URL, use this Theme
341
+ </li>
342
+ <li>
343
+ <b>URL Prefix</b> - any Visitor URL that begins with this URL Prefix will use this Theme
344
+ </li>
345
+ <li>
346
+ <b>URL Prefix with Asterisk(s)</b> - URL Prefix that matches any subdirectory where Asterisk ("*") is specified
347
+ </li>
348
+ </ol>
349
+ For the third type, an Asterisk can only be specified to match the entire subdirectory name, not parts of the name:
350
+ <blockquote>
351
+ For example, using a Permalink structure that uses dates,
352
+ where a typical Post might be at URL
353
+ <code>http://example.com/wp/2014/04/13/daily-thoughts/</code>,
354
+ a URL Prefix with Asterisk entry of
355
+ <code>http://example.com/wp/*/04/*/d</code>
356
+ would match all April Posts with Titles that begin with the letter "d", no matter what year they were posted.
357
+ </blockquote>
358
+ </p>
359
+ </p>
360
+ Beginning with Version 5.0, <code>keyword=value</code> Queries are now supported in all URLs
361
+ (on this Settings tab;
362
+ Site Aliases may not include Queries).
363
+ </p>
364
+ <?php
365
+ }
366
+
367
+ function jr_mt_echo_add_is_prefix() {
368
+ echo '<input type="radio" id="add_is_prefix" name="jr_mt_settings[add_is_prefix]" value="false" checked="checked" /> URL';
369
+ ?>
370
+ <br/>
371
+ <input type="radio" id="add_is_prefix" name="jr_mt_settings[add_is_prefix]" value="prefix" /> URL Prefix<br/>
372
+ <input type="radio" id="add_is_prefix" name="jr_mt_settings[add_is_prefix]" value="*" /> URL Prefix with Asterisk ("*")
373
+ <?php
374
+ }
375
+
376
+ function jr_mt_echo_add_theme() {
377
+ jr_mt_themes_field( 'add_theme', '', 'jr_mt_settings', FALSE );
378
+ }
379
+
380
+ function jr_mt_echo_add_path_id() {
381
+ ?>
382
+ <input id="add_path_id" name="jr_mt_settings[add_path_id]" type="text" size="75" maxlength="256" value="" />
383
+ <br />
384
+ &nbsp;
385
+ (cut and paste URL here of Page, Post, Prefix or other)
386
+ <br />
387
+ &nbsp;
388
+ URL must begin with
389
+ the current
390
+ <a href="options-general.php">Site Address (URL)</a>:
391
+ <?php
392
+ echo '<code>' . JR_MT_HOME_URL . '/</code>.';
393
+ }
394
+
395
+ /**
396
+ * Section text for Section4
397
+ *
398
+ * Display an explanation of this Section
399
+ *
400
+ */
401
+ function jr_mt_querykw_expl() {
402
+ ?>
403
+ <p>
404
+ Select a Theme to use
405
+ whenever the specified Query Keyword (<code>?keyword=</code> or <code>&keyword=</code>)
406
+ is found in the URL of
407
+ any Page, Post or
408
+ any other non-Admin page.
409
+ And click any of the <b>Save All Changes</b> buttons to add the entry.
410
+ </p>
411
+ <p>
412
+ <b>
413
+ Note
414
+ </b>
415
+ that Query Keyword takes precedence over all other types of Theme selection entries.
416
+ For example,
417
+ <?php
418
+ echo '<code>' . JR_MT_HOME_URL . '?firstname=dorothy</code>'
419
+ . ' would use the Theme specified for the <code>firstname</code> keyword, not the Theme specified for Site Home.'
420
+ . ' Query matching is case-insensitive, so all Keywords entered are stored in lower-case.</p>';
421
+ }
422
+ function jr_mt_echo_add_querykw_theme() {
423
+ jr_mt_themes_field( 'add_querykw_theme', '', 'jr_mt_settings', FALSE );
424
+ }
425
+ function jr_mt_echo_add_querykw_keyword() {
426
+ $three_dots = '&#133;';
427
+ echo '<code>'
428
+ . JR_MT_HOME_URL
429
+ . "/</code>$three_dots<code>/?"
430
+ . '<input id="add_querykw_keyword" name="jr_mt_settings[add_querykw_keyword]" type="text" size="20" maxlength="64" value="" />=</code>'
431
+ . $three_dots;
432
+ }
433
+
434
+ /**
435
+ * Section text for Section5
436
+ *
437
+ * Display an explanation of this Section
438
+ *
439
+ */
440
+ function jr_mt_query_expl() {
441
+ ?>
442
+ <p>
443
+ Select a Theme to use
444
+ whenever the specified Query Keyword <b>and</b> Value (<code>?keyword=value</code> or <code>&keyword=value</code>)
445
+ are found in the URL of
446
+ any Page, Post or
447
+ any other non-Admin page.
448
+ And click any of the <b>Save All Changes</b> buttons to add the entry.
449
+ </p>
450
+ <p>
451
+ <b>
452
+ Note
453
+ </b>
454
+ that Query Keyword=Value takes precedence over all other Theme selection entries,
455
+ including a Query Keyword entry for the same Keyword.
456
+ For example,
457
+ <?php
458
+ echo '<code>' . JR_MT_HOME_URL . '?firstname=dorothy</code>'
459
+ . ' would use the Theme specified for the <code>firstname=dorothy</code> keyword=value pair,'
460
+ . ' not the Theme specified for Site Home nor even the Theme specified for the Keyword <code>firstname</code>.'
461
+ . ' Query matching is case-insensitive, so all Keywords and Values entered are stored in lower-case.</p>';
462
+ }
463
+ function jr_mt_echo_add_query_theme() {
464
+ jr_mt_themes_field( 'add_query_theme', '', 'jr_mt_settings', FALSE );
465
+ }
466
+ function jr_mt_echo_add_query_keyword() {
467
+ $three_dots = '&#133;';
468
+ echo '<code>'
469
+ . JR_MT_HOME_URL
470
+ . "/</code>$three_dots<code>/?"
471
+ . '<input id="add_query_keyword" name="jr_mt_settings[add_query_keyword]" type="text" size="20" maxlength="64" value="" /></code>';
472
+ }
473
+ function jr_mt_echo_add_query_value() {
474
+ echo '<code>'
475
+ . '='
476
+ . '<input id="add_query_value" name="jr_mt_settings[add_query_value]" type="text" size="20" maxlength="64" value="" /></code>';
477
+ }
478
+
479
+ function jr_mt_aliases_expl() {
480
+ ?>
481
+ <p>
482
+ Define any
483
+ <b>
484
+ Site Aliases
485
+ </b>
486
+ that may be used to access your WordPress website.
487
+ </p>
488
+ <p>
489
+ This plugin uses the value of
490
+ <b>
491
+ Site Address (URL)
492
+ </b>
493
+ defined on the
494
+ <a href="options-general.php">
495
+ General Settings</a>
496
+ Admin panel
497
+ to match URLs against the Theme Selection settings.
498
+ By default, when the plugin is first installed,
499
+ or the value of Site Address changed,
500
+ a
501
+ <i>
502
+ www Alias Entry
503
+ </i>
504
+ is automatically defined
505
+ to handle the most common Alias used on WordPress sites:
506
+ by adding or removing the "www." prefix of the Domain Name.
507
+ </p>
508
+ <p>
509
+ If your WordPress website is accessed by
510
+ anything other than the Site Address or Site Aliases defined below,
511
+ this Plugin will always use the WordPress Active Theme defined on the
512
+ <a href="themes.php">
513
+ Appearance-Themes</a>
514
+ Admin panel.
515
+ </p>
516
+ <p>
517
+ Although by no means exhaustive,
518
+ this list can help you remember where you might have defined Aliases that need to be defined below.
519
+ </p>
520
+ <ul class="jrmtpoints">
521
+ <?php
522
+ if ( is_multisite() ) {
523
+ echo '<li><b>Mapped Domain</b>. Plugins such as <a href="https://wordpress.org/plugins/wordpress-mu-domain-mapping/">WordPress MU Domain Mapping</a> allow each Site in a WordPress Network to have its own Domain Name.</li>';
524
+ }
525
+ ?>
526
+ <li>
527
+ <b>IP Address</b>.
528
+ Most sites can be accessed by an IP address,
529
+ either the IPv4 format of four numbers separated by dots (168.1.0.1)
530
+ or the newer IPv6 format of several hexadecimal numbers separated by colons (2001:0DB8:AC10:FE01::).
531
+ </li>
532
+ <li>
533
+ <b>Parked Domain</b>.
534
+ example.com might have example.club as a Alias defined as a Parked Domain to your web host.
535
+ </li>
536
+ <li>
537
+ <b>ServerAlias</b> or equivalent.
538
+ Apache allows one or more Domain or Subdomain aliases to be defined with the SeverAlias directive;
539
+ non-Apache equivalents offer similar capabilities.
540
+ </li>
541
+ <li>
542
+ <b>Redirection</b>.
543
+ Most domain name registration and web hosting providers also offer a Redirection service.
544
+ Optionally, Redirection can be Masked (or not) to keep the redirected URL in the browser's address bar.
545
+ </li>
546
+ <li>
547
+ <b>.htaccess RewriteRule</b> or equivalent.
548
+ Each directory can contain a hidden file named
549
+ <code>.htaccess</code>.
550
+ These files may include RewriteRule statements that modify the URL
551
+ to change the URL of a site
552
+ as it appears in the Site Visitor's web browser address bar
553
+ from,
554
+ for example,
555
+ <code>http://example.com/wordpress</code>
556
+ to
557
+ <code>http://example.com</code>.
558
+ </li>
559
+ </ul>
560
+ <?php
561
+ }
562
+
563
+ function jr_mt_delete_aliases_expl() {
564
+ ?>
565
+ <p>
566
+ Here you can see,
567
+ and are able to delete,
568
+ any Site Aliases that have been created in the
569
+ Create New Sites Alias Entry section below,
570
+ or were created by default by this Plugin
571
+ for the current Site Address (URL) defined on the
572
+ <a href="options-general.php">General Settings</a>
573
+ Admin panel:
574
+ <?php
575
+ echo '<code>' . JR_MT_HOME_URL. '</code></p>';
576
+ }
577
+
578
+ function jr_mt_echo_delete_alias_entry() {
579
+ $settings = get_option( 'jr_mt_settings' );
580
+ echo '<p>In addition to the <a href="options-general.php">Site Address (URL)</a> <code>'
581
+ . JR_MT_HOME_URL
582
+ . '</code>, this Plugin will also control Themes for the following Site Aliases:</p><ol>';
583
+ foreach ( $settings['aliases'] as $array_index => $alias ) {
584
+ /* Do not allow the Site URL ("Home") alias to be deleted.
585
+ In fact, do not even display it.
586
+ */
587
+ if ( !$alias['home'] ) {
588
+ echo '<li>Delete <input type="checkbox" id="del_alias_entry" name="jr_mt_settings[del_alias_entry][]" value="'
589
+ . $array_index
590
+ . '"> <code>'
591
+ . $alias['url']
592
+ . '</code></li>';
593
+ }
594
+ }
595
+ echo '</ol>';
596
+ }
597
+
598
+ function jr_mt_create_alias_expl() {
599
+ echo '<p>To add another Site Alias, cut and paste its URL below.</p>';
600
+ }
601
+
602
+ function jr_mt_echo_add_alias() {
603
+ ?>
604
+ <input id="add_alias" name="jr_mt_settings[add_alias]" type="text" size="75" maxlength="256" value="" />
605
+ <br />
606
+ &nbsp;
607
+ (cut and paste URL of a new Site Alias here)
608
+ <br />
609
+ &nbsp;
610
+ URL must begin with
611
+ <code>http://</code>
612
+ or
613
+ <code>https://</code>
614
+ <?php
615
+ }
616
+
617
+ /**
618
+ * Section text for Section6
619
+ *
620
+ * Display an explanation of this Section
621
+ *
622
+ */
623
+ function jr_mt_sticky_expl() {
624
+ /* "Membership System V2" is a paid plugin that blocks (our sticky) Cookies
625
+ */
626
+ global $jr_mt_plugins_cache;
627
+ foreach ( $jr_mt_plugins_cache as $rel_path => $plugin_data ) {
628
+ if ( 0 === strncasecmp( 'memberium', $rel_path, 9 ) ) {
629
+ echo '<b><u>IMPORTANT</u></b>: The Sticky feature of this plugin does not work with the <b>Membership System V2</b> plugin, which blocks the required Cookies. At least one plugin from memberium.com appears to have been installed: '
630
+ . $plugin_data['Name'];
631
+ break;
632
+ }
633
+ }
634
+ ?>
635
+ <p>
636
+ If one of the
637
+ <b>
638
+ Keyword=Value Entries
639
+ </b>
640
+ shown below
641
+ (if any)
642
+ is present in the URL of a WordPress non-Admin webpage on the current WordPress Site
643
+ and that Entry is:
644
+ <ol>
645
+ <li>
646
+ <b>Sticky</b>,
647
+ then the specified Theme will continue to be displayed for subsequent
648
+ WordPress non-Admin webpages
649
+ viewed by the same Visitor
650
+ until an Override entry is encountered by the same Visitor.
651
+ </li>
652
+ <li>
653
+ <b>Override</b>,
654
+ then the specified Theme will be displayed,
655
+ effectively ending any previous Sticky Theme that was being displayed
656
+ for the same Visitor.
657
+ </li>
658
+ </ol>
659
+ <b>
660
+ Note
661
+ </b>
662
+ that,
663
+ as explained in the
664
+ Query Keyword=Value
665
+ section on the Settings tab,
666
+ Query Keyword=Value already takes precedence over all other Theme selection entries,
667
+ even without the Override checkbox selected.
668
+ Override is only intended to cancel a Sticky entry
669
+ and display the specified Theme on the current WordPress non-Admin webpage.
670
+ </p>
671
+ <p>
672
+ Implementation Notes:
673
+ <ol>
674
+ <li>
675
+ The term "Same Visitor",
676
+ used above,
677
+ refers to a single combination of
678
+ computer, browser and possibly computer user name,
679
+ if the visitor's computer has multiple accounts or user names.
680
+ A computer could be a smartphone, tablet, laptop, desktop or other Internet access device used by the Visitor.
681
+ </li>
682
+ <li>
683
+ When Sticky is active for a given Visitor,
684
+ the associated Query Keyword=Value is added to the
685
+ URL of links displayed on the current WordPress non-Admin webpage.
686
+ With the following exceptions:
687
+ <ul>
688
+ <li>
689
+ a)
690
+ Only links pointing to non-Admin webpages of the current WordPress Site are altered.
691
+ </li>
692
+ <li>
693
+ b)
694
+ The
695
+ "When to add Sticky Query to a URL"
696
+ setting below also controls when a Sticky Keyword=Value is added to a URL.
697
+ </li>
698
+ </ul>
699
+ <li>
700
+ Cookies are used for Sticky entries. If the visitor's browser refuses Cookies,
701
+ or another Plugin blocks cookies,
702
+ this setting will not work and no error messages will be displayed.
703
+ </li>
704
+ </ol>
705
+ </p>
706
+ <p>
707
+ <b>
708
+ Important:
709
+ </b>
710
+ the Sticky feature cannot be made to work in all WordPress environments.
711
+ Timing, Cookie and other issues may be caused by other plugins, themes and visitor browser settings,
712
+ so please test carefully and realize that the solution to some problems will involve a choice between not using the Sticky feature and not using a particular plugin or theme.
713
+ </p>
714
+ <?php
715
+ }
716
+
717
+ function jr_mt_echo_query_present() {
718
+ $settings = get_option( 'jr_mt_settings' );
719
+ /*
720
+ FALSE if Setting "Append if no question mark ("?") found in URL", or
721
+ TRUE if Setting "Append if no Override keyword=value found in URL"
722
+ */
723
+ echo '<input type="radio" id="query_present" name="jr_mt_settings[query_present]" value="false" ';
724
+ checked( $settings['query_present'], FALSE );
725
+ echo ' /> Append if no question mark ("?") found in URL<br/><input type="radio" id="query_present" name="jr_mt_settings[query_present]" value="true" ';
726
+ checked( $settings['query_present'] );
727
+ echo ' /> Append if no Override <code>keyword=value</code> found in URL';
728
+ }
729
+
730
+ function jr_mt_echo_sticky_query_entry() {
731
+ global $jr_mt_kwvalsep;
732
+ $settings = get_option( 'jr_mt_settings' );
733
+ $three_dots = '&#133;';
734
+ $first = TRUE;
735
+ if ( !empty( $settings['query'] ) ) {
736
+ foreach ( $settings['query'] as $keyword => $value_array ) {
737
+ foreach ( $value_array as $value => $theme ) {
738
+ if ( '*' !== $value ) {
739
+ if ( $first ) {
740
+ $first = FALSE;
741
+ } else {
742
+ echo '<br />';
743
+ }
744
+ echo 'Sticky <input type="checkbox" id="sticky_query_entry" name="jr_mt_settings[sticky_query_entry][]" value="'
745
+ . "$keyword$jr_mt_kwvalsep$value"
746
+ . '" ';
747
+ checked( isset( $settings['remember']['query'][$keyword][$value] ) );
748
+ echo ' /> &nbsp; Override <input type="checkbox" id="override_query_entry" name="jr_mt_settings[override_query_entry][]" value="'
749
+ . "$keyword$jr_mt_kwvalsep$value"
750
+ . '" ';
751
+ checked( isset( $settings['override']['query'][$keyword][$value] ) );
752
+ echo ' /> &nbsp; Theme='
753
+ . wp_get_theme( $theme )->Name . '; '
754
+ . 'Query='
755
+ . '<code>'
756
+ . JR_MT_HOME_URL
757
+ . "/</code>$three_dots<code>/?"
758
+ . "<b><input type='text' readonly='readonly' disable='disabled' name='jr_mt_stkw' value='$keyword' size='"
759
+ . jr_mt_strlen( $keyword )
760
+ . "' /></b>"
761
+ . '='
762
+ . "<b><input type='text' readonly='readonly' disable='disabled' name='jr_mt_stkwval' value='$value' size='"
763
+ . jr_mt_strlen( $value )
764
+ . "' /></b></code>";
765
+ }
766
+ }
767
+ }
768
+ }
769
+ if ( $first ) {
770
+ echo 'None';
771
+ }
772
+ }
773
+
774
+ function jr_mt_everything_expl() {
775
+ ?>
776
+ <p>
777
+ <b>Theme for Everything</b>
778
+ simplifies the use of a Theme with Theme Settings that you need to change frequently,
779
+ when the Theme is only going to be used on one or more Pages or Posts.
780
+ The Theme can be set as the WordPress Active Theme through the Appearance-Themes admin panel,
781
+ and set for specific Pages or Posts using this plugin's settings (on Settings tab),
782
+ with another Theme specified below as the plugin's default theme ("Theme for Everything").
783
+ </p>
784
+ <?php
785
+ }
786
+
787
+ function jr_mt_echo_current() {
788
+ $settings = get_option( 'jr_mt_settings' );
789
+ jr_mt_themes_field( 'current', $settings['current'], 'jr_mt_settings', TRUE );
790
+ echo '<br /> &nbsp; (select blank entry for default: WordPress Active Theme defined in Appearance-Themes, currently <b>' . wp_get_theme()->Name . '</b>)';
791
+ }
792
+
793
+ function jr_mt_all_settings_expl() {
794
+ ?>
795
+ <p>
796
+ These are
797
+ <b>
798
+ Advanced Setting
799
+ </b>
800
+ because they may not work with every other plugin, theme or permalinks setting.
801
+ This plugin is only able to determine whether what is about to be displayed at the current URL
802
+ is a Page or Post
803
+ after all other Plugins have been loaded;
804
+ the one exception to this is the Default setting for Permalinks,
805
+ when <code>?p=</code> and <code>?page_id=</code> are used.
806
+ </p>
807
+ <p>
808
+ Some other plugins and themes request the name of the current Theme
809
+ <i>
810
+ too early,
811
+ </i>
812
+ while they are being loaded,
813
+ which is before this plugin is able to determine if it is on a Page or Post.
814
+ For this reason,
815
+ using either of these settings may not work properly for all other plugins and themes.
816
+ As a result,
817
+ if you choose to use either or both of these two settings,
818
+ careful testing is advised immediately
819
+ <u>and</u>
820
+ whenever you change the Permalink setting, activate a plugin or start using a different theme.
821
+ </p>
822
+ <p>
823
+ In this section, you can select a different Theme for All Pages and/or All Posts.
824
+ To remove a previously selected Theme, select the blank entry from the drop-down list.
825
+ </p>
826
+ <p>
827
+ On the Settings tab, you were able to select a Theme, including WordPress' Active Theme, to override any choice you make here, for individual Pages, Posts or
828
+ any other non-Admin pages that have their own Permalink; for example, specific Archive or Category pages.
829
+ Or groups of Pages, Posts or any other non-Admin pages that share the same URL Prefix.
830
+ </p>
831
+ <p>
832
+ The Settings tab also has a Query Keyword section
833
+ that allows
834
+ you to select a Theme to use whenever a specified
835
+ Query Keyword (<code>?keyword=value</code> or <code>&keyword=value</code>)
836
+ appears in the URL of any Page, Post or other non-Admin page.
837
+ </p>
838
+ <?php
839
+ }
840
+
841
+ function jr_mt_echo_all_things( $thing ) {
842
+ $settings = get_option( 'jr_mt_settings' );
843
+ $field = 'all_' . jr_mt_strtolower( $thing['thing'] );
844
+ jr_mt_themes_field( $field, $settings[$field], 'jr_mt_settings', TRUE );
845
+ }
846
+
847
+ function jr_mt_ajax_expl() {
848
+ ?>
849
+ <p>
850
+ This setting selects a Theme for URLs
851
+ that include
852
+ <code>admin-ajax.php</code>,
853
+ a common WordPress technique for using AJAX.
854
+ If more than one Theme or Plugin uses AJAX in this manner,
855
+ then this Advanced Setting probably will not work correctly.
856
+ </p>
857
+ <p>
858
+ If the URL also contains a Query
859
+ (<code>?keyword=value</code>),
860
+ a Query Setting is almost always a better choice than this Advanced Setting.
861
+ </p>
862
+ <?php
863
+ }
864
+
865
+ function jr_mt_echo_ajax_all() {
866
+ $settings = get_option( 'jr_mt_settings' );
867
+ jr_mt_themes_field( 'ajax_all', $settings['ajax_all'], 'jr_mt_settings', TRUE );
868
+ }
869
+
870
+ ?>
includes/admin-validate.php ADDED
@@ -0,0 +1,452 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /* Exit if .php file accessed directly
4
+ */
5
+ if ( !defined( 'ABSPATH' ) ) {
6
+ exit;
7
+ }
8
+
9
+ function jr_mt_validate_settings( $input ) {
10
+ global $jr_mt_kwvalsep;
11
+ $valid = array();
12
+
13
+ $prefix_types = array(
14
+ 'false' => 'url',
15
+ 'prefix' => 'url_prefix',
16
+ '*' => 'url_asterisk'
17
+ );
18
+
19
+ $settings = get_option( 'jr_mt_settings' );
20
+ $query = $settings['query'];
21
+ $aliases = $settings['aliases'];
22
+
23
+ /* Begin by deciding which Tab to display on the plugin's Settings page
24
+
25
+ Default value should never be used if plugin is written correctly.
26
+ */
27
+ $tab = 1;
28
+ for ( $i = 1; $i <= 6; $i++ ) {
29
+ if ( isset( $input[ "tab$i" ] ) ) {
30
+ $tab = $i;
31
+ break;
32
+ }
33
+ }
34
+ set_transient( 'jr_mt_' . get_current_user_id() . '_tab', $tab, 5 );
35
+
36
+ if ( isset( $input['permalink'] ) ) {
37
+ $internal_settings = get_option( 'jr_mt_internal_settings' );
38
+ $internal_settings['permalink'] = get_option( 'permalink_structure' );
39
+ update_option( 'jr_mt_internal_settings', $internal_setting );
40
+ }
41
+
42
+ foreach ( array( 'all_pages', 'all_posts', 'site_home', 'current', 'ajax_all' ) as $thing ) {
43
+ $valid[$thing] = $input[$thing];
44
+ }
45
+
46
+ foreach ( $prefix_types as $key => $thing ) {
47
+ $valid[$thing] = $settings[$thing];
48
+ }
49
+ $remember = array( 'query' => array() );
50
+ if ( isset( $input['sticky_query_entry'] ) ) {
51
+ foreach ( $input['sticky_query_entry'] as $query_entry ) {
52
+ list( $keyword, $value ) = explode( $jr_mt_kwvalsep, $query_entry );
53
+ /* Data Sanitization not required as
54
+ Keyword and Value are not entered by a human,
55
+ but extracted from previously-generated HTML.
56
+ */
57
+ $remember['query'][$keyword][$value] = TRUE;
58
+ }
59
+ }
60
+
61
+ $override = array( 'query' => array() );
62
+ if ( isset( $input['override_query_entry'] ) ) {
63
+ foreach ( $input['override_query_entry'] as $query_entry ) {
64
+ list( $keyword, $value ) = explode( $jr_mt_kwvalsep, $query_entry );
65
+ /* Data Sanitization not required as
66
+ Keyword and Value are not entered by a human,
67
+ but extracted from previously-generated HTML.
68
+ */
69
+ $override['query'][$keyword][$value] = TRUE;
70
+ }
71
+ }
72
+
73
+ if ( isset ( $input['del_entry'] ) ) {
74
+ foreach ( $input['del_entry'] as $del_entry ) {
75
+ $del_array = explode( '=', $del_entry, 3 );
76
+ if ( 'query' === $del_array[0] ) {
77
+ unset( $query[ $del_array[1] ][ $del_array[2] ] );
78
+ if ( empty( $query[ $del_array[1] ] ) ) {
79
+ unset( $query[ $del_array[1] ] );
80
+ }
81
+ /* unset() does nothing if a variable or array element does not exist.
82
+ */
83
+ unset( $remember['query'][ $del_array[1] ][ $del_array[2] ] );
84
+ if ( empty( $remember['query'][ $del_array[1] ] ) ) {
85
+ unset( $remember['query'][ $del_array[1] ] );
86
+ }
87
+ unset( $override['query'][ $del_array[1] ][ $del_array[2] ] );
88
+ if ( empty( $override['query'][ $del_array[1] ] ) ) {
89
+ unset( $override['query'][ $del_array[1] ] );
90
+ }
91
+ } else {
92
+ /* Check for a URL entry
93
+ */
94
+ if ( 'url' === jr_mt_substr( $del_array[0], 0, 3 ) ) {
95
+ foreach ( $valid[ $del_array[0] ] as $i => $entry_array ) {
96
+ if ( $entry_array['url'] === $del_array[2] ) {
97
+ /* Cannot unset $entry_array, even if prefixed by & in foreach
98
+ */
99
+ unset( $valid[ $del_array[0] ][ $i ] );
100
+ break;
101
+ }
102
+ }
103
+ } else {
104
+ /* Must be Home, All Pages or Posts, or Everything
105
+ */
106
+ $valid[ $del_array[0] ] = '';
107
+ }
108
+ }
109
+ }
110
+ }
111
+
112
+ /* Handle troublesome %E2%80%8E UTF Left-to-right Mark (LRM) suffix first.
113
+ */
114
+ $url = jr_mt_sanitize_url( $input['add_path_id'] );
115
+
116
+ if ( ( empty( $input['add_theme'] ) && !empty( $url ) ) || ( !empty( $input['add_theme'] ) && empty( $url ) ) ) {
117
+ add_settings_error(
118
+ 'jr_mt_settings',
119
+ 'jr_mt_emptyerror',
120
+ 'Both URL and Theme must be specified to add an Individual entry',
121
+ 'error'
122
+ );
123
+ } else {
124
+ if ( !empty( $url ) ) {
125
+ if ( jr_mt_same_prefix_url( JR_MT_HOME_URL, $url ) ) {
126
+ if ( ( '*' !== $input['add_is_prefix'] ) && ( FALSE !== strpos( $url, '*' ) ) ) {
127
+ add_settings_error(
128
+ 'jr_mt_settings',
129
+ 'jr_mt_queryerror',
130
+ 'Asterisk ("*") only allowed when "URL Prefix with Asterisk" selected: <code>' . $url . '</code>',
131
+ 'error'
132
+ );
133
+ } else {
134
+ $prep_url = jr_mt_prep_url( $url );
135
+ if ( 'false' === $input['add_is_prefix'] ) {
136
+ if ( jr_mt_same_url( $prep_url, JR_MT_HOME_URL ) ) {
137
+ add_settings_error(
138
+ 'jr_mt_settings',
139
+ 'jr_mt_homeerror',
140
+ 'Please use "Select Theme for Site Home" field instead of specifying Site Home URL as an individual entry.',
141
+ 'error'
142
+ );
143
+ } else {
144
+ if ( jr_mt_same_prefix_url( $prep_url, admin_url() ) ) {
145
+ add_settings_error(
146
+ 'jr_mt_settings',
147
+ 'jr_mt_adminerror',
148
+ 'Admin Page URLs are not allowed because no known Themes alter the appearance of Admin pages: <code>' . $url . '</code>',
149
+ 'error'
150
+ );
151
+ }
152
+ }
153
+ } else {
154
+ if ( '*' === $input['add_is_prefix'] ) {
155
+ $url_dirs = explode( '/', str_replace( '\\', '/', $url ) );
156
+ foreach ( $url_dirs as $dir ) {
157
+ if ( FALSE !== strpos( $dir, '*' ) ) {
158
+ $asterisk_found = TRUE;
159
+ if ( '*' !== $dir ) {
160
+ $asterisk_not_alone = TRUE;
161
+ }
162
+ break;
163
+ }
164
+ }
165
+ if ( isset( $asterisk_found ) ) {
166
+ if ( isset( $asterisk_not_alone ) ) {
167
+ add_settings_error(
168
+ 'jr_mt_settings',
169
+ 'jr_mt_queryerror',
170
+ 'An Asterisk ("*") may only replace a full subdirectory name, not just a portion of it: <code>' . $url . '</code>',
171
+ 'error'
172
+ );
173
+ }
174
+ } else {
175
+ add_settings_error(
176
+ 'jr_mt_settings',
177
+ 'jr_mt_queryerror',
178
+ 'No Asterisk ("*") specified but "URL Prefix with Asterisk" selected: <code>' . $url . '</code>',
179
+ 'error'
180
+ );
181
+ }
182
+ }
183
+ }
184
+
185
+ function jr_mt_settings_errors() {
186
+ $errors = get_settings_errors();
187
+ if ( !empty( $errors ) ) {
188
+ foreach ( $errors as $error_array ) {
189
+ if ( 'error' === $error_array['type'] ) {
190
+ return TRUE;
191
+ }
192
+ }
193
+ }
194
+ return FALSE;
195
+ }
196
+
197
+ /* If there have been no errors detected,
198
+ create the new URL setting entry.
199
+ */
200
+ if ( !jr_mt_settings_errors() ) {
201
+ /* ['url'], ['url_prefix'] or ['url_asterisk']
202
+ */
203
+ $key = $prefix_types[ $input['add_is_prefix'] ];
204
+ $rel_url = jr_mt_relative_url( $url, JR_MT_HOME_URL );
205
+ $valid[ $key ][] = array(
206
+ 'url' => $url,
207
+ 'rel_url' => $rel_url,
208
+ 'theme' => $input['add_theme']
209
+ );
210
+ /* Get index of element just added to array $valid[ $key ]
211
+ */
212
+ end( $valid[ $key ] );
213
+ $valid_key = key( $valid[ $key ] );
214
+ /* Create the URL Prep array for each of the current Site Aliases,
215
+ including the Current Site URL
216
+ */
217
+ foreach ( $aliases as $index => $alias ) {
218
+ $valid[ $key ][ $valid_key ]['prep'][] = jr_mt_prep_url( $alias['url'] . '/' . $rel_url );
219
+ }
220
+ /* Only for URL type Setting, not Prefix types.
221
+ */
222
+ if ( 'url' === $key ) {
223
+ /* Try and figure out ID and WordPress Query Keyword for Type, if possible and relevant
224
+ */
225
+ if ( ( 0 === ( $id = url_to_postid( $url ) ) ) &&
226
+ ( version_compare( get_bloginfo( 'version' ), '4', '>=' ) ) ) {
227
+ $id = attachment_url_to_postid( $url );
228
+ }
229
+ if ( !empty( $id ) ) {
230
+ /* Type Cast ID as String, to match ?p=id Query in URL after Prep
231
+ */
232
+ $valid[ $key ][ $valid_key ]['id'] = (string) $id;
233
+ if ( NULL !== ( $post = get_post( $id ) ) ) {
234
+ switch ( $post->post_type ) {
235
+ case 'post':
236
+ $valid[ $key ][ $valid_key ]['id_kw'] = 'p';
237
+ break;
238
+ case 'page':
239
+ $valid[ $key ][ $valid_key ]['id_kw'] = 'page_id';
240
+ break;
241
+ case 'attachment':
242
+ $valid[ $key ][ $valid_key ]['id_kw'] = 'attachment_id';
243
+ break;
244
+ }
245
+ }
246
+ }
247
+ }
248
+ }
249
+ }
250
+ } else {
251
+ add_settings_error(
252
+ 'jr_mt_settings',
253
+ 'jr_mt_urlerror',
254
+ ' URL specified is not part of current WordPress web site: <code>'
255
+ . $url
256
+ . '</code>. URL must begin with <code>'
257
+ . JR_MT_HOME_URL
258
+ . '</code>.',
259
+ 'updated'
260
+ );
261
+ }
262
+ }
263
+ }
264
+
265
+ /* Make sure reserved characters are not used
266
+ in URL Query keyword or value fields on Settings page.
267
+ */
268
+ function jr_mt_query_chars( $element, $where ) {
269
+ foreach (
270
+ array(
271
+ '=' => 'Equals Sign' ,
272
+ '?' => 'Question Mark' ,
273
+ '&' => 'Ampersand' ,
274
+ ' ' => 'Blank' ,
275
+ '#' => 'Number Sign' ,
276
+ '/' => 'Slash' ,
277
+ '\\' => 'Backslash' ,
278
+ '[' => 'Square Bracket',
279
+ ']' => 'Square Bracket'
280
+ ) as $char => $name ) {
281
+ if ( FALSE !== strpos( $element, $char ) ) {
282
+ add_settings_error(
283
+ 'jr_mt_settings',
284
+ 'jr_mt_queryerror',
285
+ 'Illegal character used in '
286
+ . $where
287
+ . ': '
288
+ . $name
289
+ . ' ("' . $char . '") in "'
290
+ . $element
291
+ . '"',
292
+ 'error'
293
+ );
294
+ return FALSE;
295
+ }
296
+ }
297
+ return TRUE;
298
+ }
299
+ /* Data Sanitization needed here
300
+ */
301
+ $keyword = jr_mt_prep_query_keyword( $input['add_querykw_keyword'] );
302
+ if ( !empty( $input['add_querykw_theme'] ) && !empty( $keyword ) ) {
303
+ if ( jr_mt_query_chars( $keyword, 'Query Keyword' ) ) {
304
+ /* If there is an existing entry for the Keyword,
305
+ then replace it.
306
+ Otherwise, create a new entry.
307
+ */
308
+ $query[ $keyword ]['*'] = $input['add_querykw_theme'];
309
+ }
310
+ } else {
311
+ if ( !( empty( $input['add_querykw_theme'] ) && empty( $keyword ) ) ) {
312
+ add_settings_error(
313
+ 'jr_mt_settings',
314
+ 'jr_mt_emptyerror',
315
+ 'Both Query Keyword and Theme must be specified to add an Individual Query Keyword entry',
316
+ 'error'
317
+ );
318
+ }
319
+ }
320
+
321
+ /* Data Sanitization needed here
322
+ */
323
+ $keyword = jr_mt_prep_query_keyword( $input['add_query_keyword'] );
324
+ $value = jr_mt_prep_query_value( $input['add_query_value'] );
325
+ if ( !empty( $input['add_query_theme'] ) && !empty( $keyword ) && !empty( $value ) ) {
326
+ if ( jr_mt_query_chars( $keyword, 'Query Keyword' ) && jr_mt_query_chars( $value, 'Query Value' ) ) {
327
+ /* If there is an existing entry for the Keyword and Value pair,
328
+ then replace it.
329
+ Otherwise, create a new entry.
330
+
331
+ Be sure that a numeric Keyword or Value still is type String.
332
+ */
333
+ $query[ $keyword ][ $value ] = $input['add_query_theme'];
334
+ }
335
+ } else {
336
+ if ( !( empty( $input['add_query_theme'] ) && empty( $keyword ) && empty( $value ) ) ) {
337
+ add_settings_error(
338
+ 'jr_mt_settings',
339
+ 'jr_mt_emptyerror',
340
+ 'Query Keyword, Value and Theme must all be specified to add an Individual Query entry',
341
+ 'error'
342
+ );
343
+ }
344
+ }
345
+
346
+ if ( 'true' === $input['query_present'] ) {
347
+ $valid['query_present'] = TRUE;
348
+ } else {
349
+ if ( 'false' === $input['query_present'] ) {
350
+ $valid['query_present'] = FALSE;
351
+ }
352
+ }
353
+
354
+ /* Handle Alias tab
355
+
356
+ Always handle Delete first, to allow Replacement (Delete then Add)
357
+ */
358
+ if ( isset ( $input['del_alias_entry'] ) ) {
359
+ foreach ( $input['del_alias_entry'] as $del_alias_entry ) {
360
+ $int_key = (int) $del_alias_entry;
361
+ unset( $aliases[ $int_key ] );
362
+ /* Now go through all the URL-based Settings,
363
+ and delete the Prep for the deleted Alias.
364
+
365
+ $int_key is the array integer key of the just-deleted
366
+ Alias, as that will also be the array key for each of the
367
+ Settings ['prep'] arrays.
368
+ */
369
+ foreach ( $prefix_types as $form_prefix => $settings_prefix ) {
370
+ foreach ( $valid[ $settings_prefix ] as $key => $url_entry ) {
371
+ unset( $valid[ $settings_prefix ][ $key ]['prep'][ $int_key ] );
372
+ }
373
+ }
374
+ }
375
+ }
376
+ $alias_url = jr_mt_sanitize_url( $input['add_alias'] );
377
+ if ( !empty( $alias_url ) ) {
378
+ /* URL has been trimmed but Case has not been altered
379
+ */
380
+ if ( ( ( 0 !== substr_compare( $alias_url, 'http://', 0, 7, TRUE ) )
381
+ && ( 0 !== substr_compare( $alias_url, 'https://', 0, 8, TRUE ) )
382
+ )
383
+ || ( FALSE === ( $parse_url = parse_url( $alias_url ) ) ) ) {
384
+ add_settings_error(
385
+ 'jr_mt_settings',
386
+ 'jr_mt_badurlerror',
387
+ "Alias URL specified is invalid: <code>$url</code>",
388
+ 'error'
389
+ );
390
+ } else {
391
+ $url_ok = TRUE;
392
+ foreach ( array( 'user', 'pass', 'query', 'fragment' ) as $component ) {
393
+ if ( isset( $parse_url[ $component ] ) ) {
394
+ $url_ok = FALSE;
395
+ break;
396
+ }
397
+ }
398
+ if ( $url_ok ) {
399
+ /* Be sure there is NOT a trailing slash
400
+ */
401
+ $alias_url = rtrim( $alias_url, '/\\' );
402
+ $aliases[] = array(
403
+ 'url' => $alias_url,
404
+ 'prep' => jr_mt_prep_url( $alias_url ),
405
+ 'home' => FALSE
406
+ );
407
+ /* Now go through all the URL-based Settings,
408
+ and add a Prep for the new Alias.
409
+
410
+ First, determine the array integer key of the newly-added
411
+ Alias, as that will also be the array key for each of the
412
+ Settings ['prep'] arrays.
413
+ */
414
+ end( $aliases );
415
+ $prep_key = key( $aliases );
416
+
417
+ foreach ( $prefix_types as $form_prefix => $settings_prefix ) {
418
+ foreach ( $valid[ $settings_prefix ] as $key => $url_entry ) {
419
+ $valid[ $settings_prefix ][ $key ]['prep'][ $prep_key ] = jr_mt_prep_url(
420
+ $alias_url . '/' . $valid[ $settings_prefix ][ $key ]['rel_url']
421
+ );
422
+ }
423
+ }
424
+ } else {
425
+ add_settings_error(
426
+ 'jr_mt_settings',
427
+ 'jr_mt_badurlerror',
428
+ 'Alias URL cannot contain user, password, query ("?") or fragment ("#"): <code>'
429
+ . "$url</code>",
430
+ 'error'
431
+ );
432
+ }
433
+ }
434
+ }
435
+
436
+ $errors = get_settings_errors();
437
+ if ( empty( $errors ) ) {
438
+ add_settings_error(
439
+ 'jr_mt_settings',
440
+ 'jr_mt_saved',
441
+ 'Settings Saved',
442
+ 'updated'
443
+ );
444
+ }
445
+ $valid['query'] = $query;
446
+ $valid['remember'] = $remember;
447
+ $valid['override'] = $override;
448
+ $valid['aliases'] = $aliases;
449
+ return $valid;
450
+ }
451
+
452
+ ?>
includes/admin.php CHANGED
@@ -1,18 +1,50 @@
1
  <?php
2
- // Admin Page
 
 
 
 
3
 
4
- add_action( 'admin_menu', 'jr_mt_admin_hook' );
 
 
 
5
 
6
- /**
7
- * Add Admin Menu item for plugin
8
- *
9
- * Plugin needs its own Page in the Settings section of the Admin menu.
10
- *
11
- */
12
- function jr_mt_admin_hook() {
13
- // Add Settings Page for this Plugin
14
- add_theme_page( 'jonradio Multiple Themes', 'Multiple Themes plugin', 'manage_options', 'jr_mt_settings', 'jr_mt_settings_page' );
15
- add_options_page( 'jonradio Multiple Themes', 'Multiple Themes plugin', 'manage_options', 'jr_mt_settings', 'jr_mt_settings_page' );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
16
  }
17
 
18
  /**
@@ -22,364 +54,1178 @@ function jr_mt_admin_hook() {
22
  *
23
  */
24
  function jr_mt_settings_page() {
 
 
 
25
  echo '<div class="wrap">';
26
- screen_icon( 'plugins' );
27
- echo '<h2>jonradio Multiple Themes</h2>';
28
 
29
- // Required because it is only called automatically for Admin Pages in the Settings section
 
30
  settings_errors( 'jr_mt_settings' );
31
 
32
- $theme = wp_get_theme()->Name;
33
- global $jr_mt_options_cache;
34
- ?>
35
- <p>This plugin allows you to selectively change the Theme you have selected as your <b>Current Theme</b> in <b>Appearance-Themes</b> on the Admin panels.
36
- You can choose from any of the <b>Available Themes</b> listed on the Appearance-Themes Admin panel for:
37
- <ul>
38
- <li> &raquo; All Pages</li>
39
- <li> &raquo; All Posts</li>
40
- <li> &raquo; The Site Home</li>
41
- <li> &raquo; A Specific Page</li>
42
- <li> &raquo; A Specific Post</li>
43
- <li> &raquo; Any other non-Admin page that has its own Permalink; for example, a specific Archive or Category page</li>
44
- </ul>
45
- <?php
46
- if ( function_exists('is_multisite') && is_multisite() ) {
47
- echo "In a WordPress Network (AKA Multisite), Themes must be <b>Network Enabled</b> before they will appear as Available Themes on individual sites' Appearance-Themes panel.";
48
  }
49
- echo '</p>';
50
- echo '<p>';
51
- echo "The Current Theme is <b>$theme</b>. You will not normally need to specify it in any of the Settings on this page. The only exception would be if you specify a different Theme for All Pages or All Posts and wish to use the Current Theme for a specific Page, Post or other non-Admin page.";
52
- echo '</p>';
53
- echo '<form action="options.php" method="POST">';
54
 
55
- // Plugin Settings are displayed and entered here:
56
- settings_fields( 'jr_mt_settings' );
57
- do_settings_sections( 'jr_mt_settings_page' );
58
- echo '<p><input name="save" type="submit" value="Save Changes" class="button-primary" /></p></form>';
59
- }
60
-
61
- add_action( 'admin_init', 'jr_mt_admin_init' );
62
 
63
- /**
64
- * Register and define the settings
65
- *
66
- * Everything to be stored and/or can be set by the user
67
- *
68
- */
69
- function jr_mt_admin_init() {
70
- register_setting( 'jr_mt_settings', 'jr_mt_settings', 'jr_mt_validate_settings' );
71
- add_settings_section( 'jr_mt_all_settings_section',
72
- 'For All Pages, All Posts and/or Site Home',
73
- 'jr_mt_all_settings_expl',
74
- 'jr_mt_settings_page'
75
- );
76
- $suffix = array(
77
- 'Pages' => '<br />(Pages created with Add Page)',
78
- 'Posts' => ''
79
- );
80
- foreach ( array( 'Pages', 'Posts' ) as $thing ) {
81
- add_settings_field( 'all_' . strtolower( $thing ), "Select Theme for All $thing" . $suffix[$thing], 'jr_mt_echo_all_things', 'jr_mt_settings_page', 'jr_mt_all_settings_section',
82
- array( 'thing' => $thing ) );
83
- }
84
- add_settings_field( 'site_home',
85
- 'Select Theme for Site Home<br />(' . get_home_url() . ')',
86
- 'jr_mt_echo_site_home',
87
- 'jr_mt_settings_page',
88
- 'jr_mt_all_settings_section'
89
- );
90
- $settings = get_option( 'jr_mt_settings' );
91
- $ids = $settings['ids'];
92
- if ( !empty( $ids) ) {
93
- add_settings_section( 'jr_mt_delete_settings_section',
94
- 'To Display or Delete Theme Selections for Individual Pages or Posts',
95
- 'jr_mt_delete_settings_expl',
96
- 'jr_mt_settings_page'
97
- );
98
- add_settings_field( 'del_entry', 'Entries:', 'jr_mt_echo_delete_entry', 'jr_mt_settings_page', 'jr_mt_delete_settings_section' );
99
  }
100
- add_settings_section( 'jr_mt_single_settings_section',
101
- 'For An Individual Page, Post or other non-Admin page',
102
- 'jr_mt_single_settings_expl',
103
- 'jr_mt_settings_page'
104
- );
105
- add_settings_field( 'add_theme', 'Theme', 'jr_mt_echo_add_theme', 'jr_mt_settings_page', 'jr_mt_single_settings_section' );
106
- add_settings_field( 'add_path_id', 'URL of Page, Post, Prefix or other', 'jr_mt_echo_add_path_id', 'jr_mt_settings_page', 'jr_mt_single_settings_section' );
107
- add_settings_field( 'add_is_prefix', 'Select here if URL is a Prefix', 'jr_mt_echo_add_is_prefix', 'jr_mt_settings_page', 'jr_mt_single_settings_section' );
108
- }
109
-
110
- /**
111
- * Section text for Section1
112
- *
113
- * Display an explanation of this Section
114
- *
115
- */
116
- function jr_mt_all_settings_expl() {
117
- ?>
118
- <p>
119
- In this section, you can select a different Theme for All Pages, All Posts and/or Site Home.
120
- To remove a previously selected Theme, select the blank entry from the drop-down list.
121
- </p>
122
- <p>
123
- In the <i>next</i> section, you will be able to select a Theme, including the Current Theme, to override any choice you make here, for individual Pages, Posts or
124
- any other non-Admin pages that have their own Permalink; for example, specific Archive or Category pages.
125
- </p>
126
- <?php
127
- }
128
-
129
- function jr_mt_echo_all_things( $thing ) {
130
- $settings = get_option( 'jr_mt_settings' );
131
- $field = 'all_' . strtolower( $thing['thing'] );
132
- jr_mt_themes_field( $field, $settings[$field], 'jr_mt_settings', TRUE );
133
- }
134
-
135
- function jr_mt_echo_site_home() {
136
- $settings = get_option( 'jr_mt_settings' );
137
- jr_mt_themes_field( 'site_home', $settings['site_home'], 'jr_mt_settings', FALSE );
138
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
139
 
140
- /**
141
- * Section text for Section2
142
- *
143
- * Display an explanation of this Section
144
- *
145
- */
146
- function jr_mt_delete_settings_expl() {
147
- ?>
148
- <p>
149
- In this section, all entries are displayed for Themes selected for individual Pages, Posts
150
- and any other non-Admin pages that have their own Permalink; for example, specific Archive or Category pages.
151
- </p>
152
- <p>
153
- You can delete any of these entries by filling in the check box beside each one.
154
- To change the Theme for an entry, add the same entry with a different Theme in the section below this one.</p>
155
- <?php
156
- }
157
 
158
- function jr_mt_echo_delete_entry() {
159
- $entry_num = 0;
160
- $settings = get_option( 'jr_mt_settings' );
161
- foreach ( $settings['ids'] as $path_id => $opt_array ) {
162
- ++$entry_num;
163
- echo "Delete <input type='checkbox' id='del_entry' name='jr_mt_settings[del_entry][]' value='$path_id' /> &nbsp; Theme="
164
- . wp_get_theme( $opt_array['theme'] )->Name . '; ';
165
- if ( $path_id == '' ) {
166
- echo 'Site=<a href="' . get_home_url() . '" target="_blank">Home</a>';
167
- } else {
168
- if ( $opt_array['type'] == 'prefix' ) {
169
- echo 'Prefix=<a href="' . get_home_url() . "/$path_id" . '" target="_blank">' . "$path_id</a>";
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
170
  } else {
171
- if ( $opt_array['type'] == 'cat' ) {
172
- echo 'Category=<a href="' . get_home_url() . '/?cat=' . $opt_array['id'] . '" target="_blank">' . get_cat_name( $opt_array['id'] ) . '</a>';
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
173
  } else {
174
- if ( $opt_array['type'] == 'archive' ) {
175
- echo 'Archive=<a href="' . get_home_url() . '/?m=' . $opt_array['id'] . '" target="_blank">' . $opt_array['id'] . '</a>';
 
176
  } else {
177
- $p_array = get_posts( array( 'post_type' => 'any', 'include' => array( $path_id ) ) );
178
- if ( empty( $p_array ) ) {
179
- if ( $opt_array['type'] == 'admin' ) {
180
- echo 'Admin=<a href="' . get_home_url() . '/' . $opt_array['rel_url'] . '" target="_blank">' . "$path_id</a>";
 
 
 
 
 
181
  } else {
182
- echo 'Path=<a href="' . get_home_url() . "/$path_id" . '" target="_blank">' . "$path_id</a>";
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
183
  }
184
- } else {
185
- echo ucfirst( $p_array[0]->post_type ) . '=<a href="' . get_permalink( $path_id ) . '" target="_blank">' . $p_array[0]->post_title . '</a>';
186
  }
187
  }
188
  }
189
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
190
  }
191
- echo '<br />';
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
192
  }
193
- }
194
 
195
- /**
196
- * Section text for Section3
197
- *
198
- * Display an explanation of this Section
199
- *
200
- */
201
- function jr_mt_single_settings_expl() {
202
  ?>
 
 
 
 
 
203
  <p>
204
- Select a Theme for an individual Page, Post or
205
- any other non-Admin pages that has its own Permalink; for example, a specific Archive or Category page.
 
 
 
 
 
 
 
 
 
206
  <p>
 
 
 
 
 
 
207
  </p>
208
- Then cut and paste the URL of the desired Page, Post or other non-Admin page.
209
- And click the <b>Save Changes</b> button to add the entry.
 
 
 
 
210
  </p>
211
- <?php
212
- }
213
-
214
- function jr_mt_echo_add_theme() {
215
- jr_mt_themes_field( 'add_theme', '', 'jr_mt_settings', FALSE );
216
- }
217
-
218
- function jr_mt_echo_add_path_id() {
219
- ?>
220
- <input id="add_path_id" name="jr_mt_settings[add_path_id]" type="text" size="100" maxlength="256" value="" />
221
- <br />
222
- (cut and paste URL here of Page, Post, Prefix or other)
223
- <br />
224
- URL must begin with
225
- <?php
226
- echo trim( get_home_url(), '\ /' ) . '/';
227
- }
228
-
229
- function jr_mt_echo_add_is_prefix() {
230
- ?>
231
- <input type="checkbox" id="add_is_prefix" name="jr_mt_settings[add_is_prefix]" value="true" /> Anything that begins with this URL will use this Theme
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
232
  <?php
233
- }
234
-
235
- function jr_mt_validate_settings( $input ) {
236
- $valid = array();
237
- foreach ( array( 'all_pages', 'all_posts', 'site_home' ) as $thing ) {
238
- $valid[$thing] = $input[$thing];
239
- }
240
-
241
- $settings = get_option( 'jr_mt_settings' );
242
- $ids = $settings['ids'];
243
- if ( isset ( $input['del_entry'] ) ) {
244
- foreach ( $input['del_entry'] as $del_entry ) {
245
- unset( $ids[$del_entry] );
246
- }
247
  }
248
-
249
- $url = trim( $input['add_path_id'] );
250
- if ( ( empty( $input['add_theme'] ) && !empty( $url ) ) || ( !empty( $input['add_theme'] ) && empty( $url ) ) ) {
251
- add_settings_error(
252
- 'jr_mt_settings',
253
- 'jr_mt_emptyerror',
254
- 'Both URL and Theme must be specified to add an Individual entry',
255
- 'error'
256
- );
 
 
 
 
 
 
 
 
257
  } else {
258
- if ( !empty( $url ) ) {
259
- $validate_url = jr_mt_site_url( $url );
260
- if ( $validate_url === TRUE ) {
261
- extract( jr_mt_url_to_id( $url ) );
262
- if ( isset ( $input['add_is_prefix'] ) && ( $input['add_is_prefix'] == "true" ) ) {
263
- if ( parse_url( $url, PHP_URL_QUERY ) === NULL ) {
264
- $ids[$rel_url] = array(
265
- 'theme' => $input['add_theme'],
266
- 'type' => 'prefix',
267
- 'id' => $id,
268
- 'page_url' => $page_url,
269
- 'rel_url' => $rel_url,
270
- 'url' => $url
271
- );
272
- } else {
273
- add_settings_error(
274
- 'jr_mt_settings',
275
- 'jr_mt_queryerror',
276
- '?key=val&key=val Queries are not supported in a URL Prefix',
277
- 'error'
278
- );
279
-
280
- }
281
- } else {
282
- if ( $home ) {
283
- add_settings_error(
284
- 'jr_mt_settings',
285
- 'jr_mt_homeerror',
286
- 'Please use "Select Theme for Site Home" field instead of specifying Site Home URL as an individual entry.',
287
- 'error'
288
- );
289
- } else {
290
- if ( $type == 'admin' ) {
291
- add_settings_error(
292
- 'jr_mt_settings',
293
- 'jr_mt_adminerror',
294
- 'Admin Page URLs are not allowed because no known Themes alter the appearance of Admin pages.',
295
- 'error'
296
- );
297
- } else {
298
- if ( $id === FALSE ) {
299
- $key = $page_url;
300
- } else {
301
- $key = $id;
302
- }
303
- $ids[$key] = array(
304
- 'theme' => $input['add_theme'],
305
- 'type' => $type,
306
- 'id' => $id,
307
- 'page_url' => $page_url,
308
- 'rel_url' => $rel_url,
309
- 'url' => $url
310
- );
311
- }
312
- }
313
- }
314
- } else {
315
- add_settings_error(
316
- 'jr_mt_settings',
317
- 'jr_mt_urlerror',
318
- "Invalid URL specified for Individual page/post: '$url'. $validate_url",
319
- 'error'
320
- );
321
- }
322
- }
323
  }
324
- $errors = get_settings_errors();
325
- if ( empty( $errors ) ) {
326
- add_settings_error(
327
- 'jr_mt_settings',
328
- 'jr_mt_saved',
329
- 'Settings Saved',
330
- 'updated'
331
- );
 
 
 
332
  }
333
- $valid['ids'] = $ids;
334
- return $valid;
335
- }
336
-
337
- // Add Link to the plugin's entry on the Admin "Plugins" Page, for easy access
338
- global $jr_mt_plugin_basename;
339
- add_filter( "plugin_action_links_$jr_mt_plugin_basename", 'jr_mt_plugin_action_links', 10, 1 );
340
-
341
- /**
342
- * Creates Settings entry right on the Plugins Page entry.
343
- *
344
- * Helps the user understand where to go immediately upon Activation of the Plugin
345
- * by creating entries on the Plugins page, right beside Deactivate and Edit.
346
- *
347
- * @param array $links Existing links for our Plugin, supplied by WordPress
348
- * @param string $file Name of Plugin currently being processed
349
- * @return string $links Updated set of links for our Plugin
350
- */
351
- function jr_mt_plugin_action_links( $links ) {
352
- // The "page=" query string value must be equal to the slug
353
- // of the Settings admin page.
354
- array_push( $links, '<a href="' . get_bloginfo('wpurl') . '/wp-admin/admin.php?page=jr_mt_settings' . '">Settings</a>' );
355
- return $links;
356
- }
357
 
358
- // $theme_name is the name of the Theme's folder within the Theme directory
359
- function jr_mt_themes_field( $field_name, $theme_name, $setting, $excl_current_theme ) {
360
- echo "<select id='$field_name' name='$setting" . "[$field_name]' size='1'>";
361
- if ( empty( $theme_name ) ) {
362
- $selected = 'selected="selected"';
363
- } else {
364
- $selected = '';
 
 
 
 
 
 
 
 
 
 
365
  }
366
- echo "<option value='' $selected></option>";
367
- foreach ( wp_get_themes() as $folder => $theme_obj ) {
368
- if ( $excl_current_theme ) {
369
- if ( ( jr_mt_current_theme( 'stylesheet' ) == $theme_obj['stylesheet'] ) && ( jr_mt_current_theme( 'template' ) == $theme_obj['template'] ) ) {
370
- // Skip the Current Theme
371
- continue;
372
- }
373
  }
374
- if ( $theme_name == $folder ) {
375
- $selected = 'selected="selected"';
376
  } else {
377
- $selected = '';
378
  }
379
- $name = $theme_obj->Name;
380
- echo "<option value='$folder' $selected>$name</option>";
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
381
  }
382
- echo '</select>' . PHP_EOL;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
383
  }
384
 
 
 
 
385
  ?>
1
  <?php
2
+ /* Exit if .php file accessed directly
3
+ */
4
+ if ( !defined( 'ABSPATH' ) ) {
5
+ exit;
6
+ }
7
 
8
+ global $jr_mt_kwvalsep;
9
+ /* Everything is converted to lower-case, so upper-case letter makes a good keyword-value separator
10
+ */
11
+ $jr_mt_kwvalsep = 'A';
12
 
13
+ /* Go to Settings page to get Settings checked/fixed/initialized.
14
+
15
+ But don't display on Settings page itself.
16
+ */
17
+ if ( ( !isset( $_GET['page'] ) || ( 'jr_mt_settings' !== $_GET['page'] ) )
18
+ && ( ( FALSE === ( $internal_settings = get_option( 'jr_mt_internal_settings' ) ) )
19
+ || ( !isset( $internal_settings['v7init'] ) ) )
20
+ && ( FALSE !== get_option( 'jr_mt_settings' ) ) ) {
21
+ /* If (public) Settings do not exist, this is a new install or
22
+ re-install after deleting the plugin.
23
+ No warning is needed because the plugin will not do anything,
24
+ and the admin will naturally go the Settings to set some Theme Selections.
25
+ */
26
+ add_action( 'all_admin_notices', 'jr_mt_v7init_required' );
27
+ /**
28
+ * Warn that Private Site is turned OFF by default
29
+ *
30
+ * Put Warning on top of every Admin page (visible to Admins only)
31
+ * until Admin visits plugin's Settings page.
32
+ *
33
+ */
34
+ function jr_mt_v7init_required() {
35
+ global $jr_mt_plugin_data;
36
+ if ( current_user_can( 'manage_options' ) ) {
37
+ echo '<div class="updated"><p><b>' . $jr_mt_plugin_data['Name'] . ' plugin: Version '. $jr_mt_plugin_data['Version'] . ' update requires visit to <a href="'
38
+ . admin_url( 'options-general.php?page=jr_mt_settings' )
39
+ . '">Settings page</a> to check and update its Settings.</b></p></div>';
40
+ }
41
+ }
42
+ }
43
+
44
+ add_action( 'admin_enqueue_scripts', 'jr_mt_admin_enqueue_scripts' );
45
+ function jr_mt_admin_enqueue_scripts() {
46
+ global $jr_mt_plugin_data;
47
+ wp_enqueue_script( 'jr_mt_tabs', plugins_url() . '/' . dirname( jr_mt_plugin_basename() ) . '/js/tabs.js', array(), $jr_mt_plugin_data['Version'] );
48
  }
49
 
50
  /**
54
  *
55
  */
56
  function jr_mt_settings_page() {
57
+ global $jr_mt_plugin_data, $jr_mt_plugins_cache;
58
+ $jr_mt_plugins_cache = get_plugins();
59
+ add_thickbox();
60
  echo '<div class="wrap">';
61
+ echo '<h2>' . $jr_mt_plugin_data['Name'] . '</h2>';
 
62
 
63
+ /* Required because it is only called automatically for Admin Pages in the Settings section
64
+ */
65
  settings_errors( 'jr_mt_settings' );
66
 
67
+ /* Return to Same Tab where button was pushed.
68
+
69
+ TODO: This should be converted to use wp_localize_script()
70
+ as described on page 356 of "Professional WordPress Plugin Development" 2011.
71
+ */
72
+ $name = 'jr_mt_' . get_current_user_id() . '_tab';
73
+ if ( FALSE === ( $tab = get_transient( $name ) ) ) {
74
+ $tab = 1;
75
+ } else {
76
+ delete_transient( $name );
 
 
 
 
 
 
77
  }
78
+ echo '<script type="text/javascript">window.onload = function() { jrMtTabs('
79
+ . $tab . ', 6 ); }</script>';
 
 
 
80
 
81
+ $theme_obj = wp_get_theme();
82
+ $theme = $theme_obj->Name;
83
+ $theme_version = $theme_obj->Version;
84
+ global $jr_mt_options_cache;
 
 
 
85
 
86
+ $current_wp_version = get_bloginfo( 'version' );
87
+
88
+ global $jr_mt_plugins_cache;
89
+
90
+ $compatible = TRUE;
91
+
92
+ // Check for incompatible plugins that have been activated: BuddyPress and Theme Test Drive
93
+ global $jr_mt_incompat_plugins;
94
+ foreach ( $jr_mt_plugins_cache as $rel_path => $plugin_data ) {
95
+ if ( in_array( $plugin_data['Name'], $jr_mt_incompat_plugins, TRUE ) && is_plugin_active( $rel_path ) ) {
96
+ if ( $compatible ) {
97
+ echo '<h3>Plugin Conflict Error Detected</h3>';
98
+ $compatible = FALSE;
99
+ }
100
+ echo '<p>This Plugin (' . $jr_mt_plugin_data['Name'] . ') cannot be used when the <b>' . $plugin_data['Name']
101
+ . '</b> plugin is Activated. If you wish to use the ' . $jr_mt_plugin_data['Name']
102
+ . ' plugin, please deactivate the ' . $plugin_data['Name']
103
+ . ' plugin (not just when viewing this Settings page, but whenever the '
104
+ . $jr_mt_plugin_data['Name'] . ' plugin is activated).</p>';
105
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
106
  }
107
+
108
+ if ( $compatible ) {
109
+ ?>
110
+ <style type="text/css">
111
+ <!--
112
+ ul.jrmtpoints { margin-left: 1em;
113
+ list-style: disc;}
114
+ -->
115
+ </style>
116
+ <h2 class="nav-tab-wrapper">
117
+ <a href="#" class="nav-tab nav-tab-active" id="jr-mt-tabs1"
118
+ onClick="jrMtTabs( 1, 6 );">Settings</a><a href="#" class="nav-tab" id="jr-mt-tabs2"
119
+ onClick="jrMtTabs( 2, 6 );">Site Aliases</a><a href="#" class="nav-tab" id="jr-mt-tabs3"
120
+ onClick="jrMtTabs( 3, 6 );">Advanced Settings</a><a href="#" class="nav-tab" id="jr-mt-tabs4"
121
+ onClick="jrMtTabs( 4, 6 );">Theme Options</a><a href="#" class="nav-tab" id="jr-mt-tabs5"
122
+ onClick="jrMtTabs( 5, 6 );">System Information</a><a href="#" class="nav-tab" id="jr-mt-tabs6"
123
+ onClick="jrMtTabs( 6, 6 );">Help</a>
124
+ </h2>
125
+ <div id="jr-mt-settings1">
126
+ <h3>Settings</h3>
127
+ <p>
128
+ This is the main Settings tab.
129
+ You should also review the
130
+ <a href="#" onClick="jrMtTabs( 2, 6 );">Site Aliases tab</a>:
131
+ </p>
132
+ <ul class="jrmtpoints">
133
+ <li>
134
+ when first using this plugin,
135
+ </li>
136
+ <li>
137
+ when upgrading from Version 5 (or earlier) of this plugin,
138
+ and
139
+ </li>
140
+ <li>
141
+ whenever you change the
142
+ <b>
143
+ Site Address (URL)
144
+ </b>
145
+ defined on the
146
+ <a href="options-general.php">
147
+ General Settings</a>
148
+ Admin panel.
149
+ </li>
150
+ </ul>
151
+ <p>
152
+ Additional Settings are available on the
153
+ <a href="#" onClick="jrMtTabs( 3, 6 );">Advanced Settings tab</a>,
154
+ but they can cause problems
155
+ in certain WordPress configurations,
156
+ so should be used with care.
157
+ </p>
158
+ <p>
159
+ Checking Settings...
160
+ </p>
161
+ <ul class="jrmtpoints">
162
+ <?php
163
+
164
+ unregister_setting( 'jr_mt_settings', 'jr_mt_settings', 'jr_mt_validate_settings' );
165
+
166
+ global $wp;
167
+ $default_internal_settings = array(
168
+ 'version' => $jr_mt_plugin_data['Version'],
169
+ 'permalink' => get_option( 'permalink_structure' ),
170
+ /* Store $wp->public_query_vars for when they are needed before 'setup_theme' Action
171
+
172
+ Note: $wp is not valid until 'setup_theme' Action.
173
+ */
174
+ 'query_vars' => $wp->public_query_vars
175
+ );
176
+ if ( is_array( $internal_settings_original = get_option( 'jr_mt_internal_settings' ) ) ) {
177
+ $internal_settings = $internal_settings_original;
178
+ /* When plugin is installed (i.e. - no Settings),
179
+ Previous Version is set to Current Version
180
+ because no Version Conversion is required.
181
+ */
182
+ if ( ( !isset( $internal_settings['version'] ) ) || ( !is_string( $internal_settings['version'] ) ) ) {
183
+ $internal_settings['version'] = $default_internal_settings['version'];
184
+ }
185
+ $internal_settings['query_vars'] = $default_internal_settings['query_vars'];
186
+ } else {
187
+ $internal_settings = $default_internal_settings;
188
+ jr_mt_messages( 'First use (or after plugin deleted): initialize Internal ("invisible") Settings' );
189
+ }
190
+ $previous_version = $internal_settings['version'];
191
+ /* Update to Current Version (which may be the same as Previous Version)
192
+ */
193
+ $internal_settings['version'] = $default_internal_settings['version'];
194
+
195
+ $internal_settings['v7init'] = TRUE;
196
 
197
+ if ( $internal_settings !== $internal_settings_original ) {
198
+ if ( update_option( 'jr_mt_internal_settings', $internal_settings ) ) {
199
+ jr_mt_messages( 'Internal ("invisible") Settings have changed and were successfully updated' );
200
+ } else {
201
+ jr_mt_messages( 'Internal ("invisible") Settings have changed but could not be updated' );
202
+ }
203
+ }
 
 
 
 
 
 
 
 
 
 
204
 
205
+ /* Check if any Settings were not properly converted from prior versions,
206
+ the Site URL has changed, or the settings are otherwise corrupted.
207
+ Do things in the following order, to avoid issues:
208
+ - check every setting exists and is of the right type
209
+ - check for still being in Version 4 settings; use upgradev5, if so
210
+ - check for still being in Version 5 settings; do my own conversion, if so
211
+ - check for pre-Version 7 format for ['prep']['query'] elements; convert
212
+ - check for "=" in ['prep']['query'] keyword or value
213
+ - remove if first char of value or last char of keyword
214
+ - delete setting if found anywhere else, and report as corrupt
215
+ - be sure ['aliases'][]['home'] is TRUE for correct URL (Site URL); if not:
216
+ - create any missing ['url'*][]['rel_url'] from ['url'*][]['url'] and
217
+ ['aliases'][]['url'] from old ['aliases'][]['home']
218
+ - change to FALSE
219
+ - set correct ['aliases'][]['home'] to TRUE, even if it means adding alias entries
220
+ - rebuild all ['url'*][]['prep']
221
+ - re-create all ['url'*][]['url'] from ['url'*][]['rel_url'] and new Site URL
222
+ - ['url'*][]['id'] is integer - convert to string
223
+ - Missing ['url'*][]['rel_url'] - create it from ['url'*][]['url'] and Site URL
224
+ - ['url'*][]['prep'] is not array - rebuild all ['url'*][]['prep']
225
+ - "?" in ['url'*][]['url'] but no query in ['url'*][]['prep'][] - rebuild this ['url'*][]['prep']
226
+ - Deleted Themes
227
+ */
228
+ if ( is_array( $settings_original = get_option( 'jr_mt_settings' ) ) ) {
229
+ $settings = $settings_original;
230
+ global $jr_mt_url_types;
231
+ $default_settings = jr_mt_default_settings();
232
+ /* Check for unconverted Version 4 Settings
233
+ */
234
+ if ( ( !isset( $settings['url'] ) )
235
+ || version_compare( $previous_version, '5', '<' ) ) {
236
+ require_once( jr_mt_path() . 'includes/upgradev5.php' );
237
+ $settings = jr_mt_convert_ids( $settings );
238
+ jr_mt_messages( 'Conversion completed to Version 5 format from Version ' . $previous_version );
239
+ }
240
+ /* Check for unconverted Version 5 Settings
241
+ */
242
+ if ( ( !isset( $settings['aliases'] ) )
243
+ || version_compare( $previous_version, '6', '<' ) ) {
244
+ $settings['aliases'] = $default_settings['aliases'];
245
+ require_once( jr_mt_path() . 'includes/upgradev6.php' );
246
+ $settings = jr_mt_convert_url_arrays( $settings );
247
+ jr_mt_messages( 'Conversion completed to Version 6 format from Version ' . $previous_version );
248
+ }
249
+ /* Check Settings for missing or wrong type entries,
250
+ including Themes that are not currently installed.
251
+ */
252
+ $jr_mt_all_themes = jr_mt_all_themes();
253
+ /* Check: 'all_pages', 'all_posts', 'site_home', 'current', 'ajax_all'
254
+ */
255
+ foreach ( array( 'all_pages', 'all_posts', 'site_home', 'current', 'ajax_all' ) as $key ) {
256
+ if ( ( !isset( $settings[ $key ] ) ) || ( !is_string( $settings[ $key ] ) ) ) {
257
+ $settings[ $key ] = $default_settings[ $key ];
258
+ jr_mt_messages( 'Home, Everything or All Pages/Posts/AJAX Setting corrupt: reset to default (WordPress Active Theme)' );
259
+ } else {
260
+ if ( ( '' !== $settings[ $key ] ) && ( !isset( $jr_mt_all_themes[ $settings[ $key ] ] ) ) ) {
261
+ $settings[ $key ] = $default_settings[ $key ];
262
+ jr_mt_messages( 'Home, Everything or All Pages/Posts/AJAX Setting deleted: specified Theme no longer exists' );
263
+ }
264
+ }
265
+ }
266
+ /* Check ['query_present']
267
+ */
268
+ if ( ( !isset( $settings['query_present'] ) ) || ( !is_bool( $settings['query_present'] ) ) ) {
269
+ $settings['query_present'] = $default_settings['query_present'];
270
+ jr_mt_messages( '"When to add Sticky Query to a URL" Setting corrupt: reset to default' );
271
+ }
272
+ /* Check ['aliases']
273
+ */
274
+ if ( ( !isset( $settings['aliases'] ) ) || ( !is_array( $settings['aliases'] ) ) ) {
275
+ $settings['aliases'] = $default_settings['aliases'];
276
+ jr_mt_messages( 'No Site Aliases defined; set to Default Aliases, if any' );
277
+ /* Relies on ['url'*] being valid, so do after it.
278
+ */
279
+ $rebuild_prep = TRUE;
280
  } else {
281
+ foreach ( $settings['aliases'] as $alias ) {
282
+ if ( ( !is_string( $alias['url'] ) )
283
+ || ( !is_array( $alias['prep'] ) )
284
+ || !is_bool( $alias['home'] ) ) {
285
+ $settings['aliases'] = $default_settings['aliases'];
286
+ jr_mt_messages( 'Site Aliases settings are corrupt; reset to Default Aliases, if any' );
287
+ $rebuild_prep = TRUE;
288
+ break;
289
+ }
290
+ }
291
+ }
292
+ /* Check [url*]
293
+ */
294
+ foreach ( $jr_mt_url_types as $url_type ) {
295
+ if ( !isset( $settings[ $url_type ] ) ) {
296
+ $settings[ $url_type ] = $default_settings[ $url_type ];
297
+ jr_mt_messages( 'URL setting(s) re-initialized' );
298
  } else {
299
+ if ( !is_array( $settings[ $url_type ] ) ) {
300
+ $settings[ $url_type ] = $default_settings[ $url_type ];
301
+ jr_mt_messages( 'URL setting(s) deleted because they are corrupt' );
302
  } else {
303
+ foreach ( $settings[ $url_type ] as $index => $url_array ) {
304
+ if ( ( !isset( $url_array['url'] ) )
305
+ || ( !isset( $url_array['prep'] ) )
306
+ || ( !isset( $url_array['theme'] ) )
307
+ || ( !is_string( $url_array['url'] ) )
308
+ || ( !is_string( $url_array['theme'] ) )
309
+ || ( !isset( $jr_mt_all_themes[ $url_array['theme'] ] ) ) ) {
310
+ unset( $settings[ $url_type ][ $index ] );
311
+ jr_mt_messages( 'URL setting deleted: either it was corrupt or specified Theme that no longer exists' );
312
  } else {
313
+ /* Be sure all ['prep'] are arrays.
314
+ If any are not, rebuild all ['prep'] entries.
315
+ */
316
+ if ( is_array( $url_array['prep'] ) ) {
317
+ /* Be sure that all ['prep'] entries have a ['query'] entry when the
318
+ URL has a Query in it, denoted by a "?".
319
+ If any not found, Rebuild all the ['prep'] entries.
320
+ */
321
+ if ( FALSE !== strpos( $url_array['url'], '?' ) ) {
322
+ foreach ( $url_array['prep'] as $prep_entry ) {
323
+ if ( isset( $prep_entry['query'] ) && is_array( $prep_entry['query'] ) ) {
324
+ /* Check for unconverted and corrupt Queries in ['prep']['query'] Settings
325
+
326
+ A Keyword ending in "=" or a Value beginning with "=" gets converted.
327
+ A "=" anywhere else means Corruption.
328
+ */
329
+ foreach ( $prep_entry['query'] as $keyword => $value_array ) {
330
+ if ( is_array( $value_array ) ) {
331
+ foreach ( $value_array as $value => $equalsign ) {
332
+ /* There must be an Equals Sign if there is a Value
333
+ */
334
+ if ( is_bool( $equalsign ) && ( $equalsign || ( '' === $value ) ) ) {
335
+ foreach ( array(
336
+ '=', '?', '&', ' ', '#', '/', '\\', '[', ']'
337
+ ) as $char ) {
338
+ if ( FALSE !== strpos( $keyword . $value, $char ) ) {
339
+ unset( $settings[ $url_type ][ $index ] );
340
+ jr_mt_messages( 'URL setting deleted: illegal character found in Query keyword or value' );
341
+ break 4;
342
+ }
343
+ }
344
+ } else {
345
+ $rebuild_prep = TRUE;
346
+ break 3;
347
+ }
348
+ }
349
+ } else {
350
+ $rebuild_prep = TRUE;
351
+ break 2;
352
+ }
353
+ }
354
+ } else {
355
+ $rebuild_prep = TRUE;
356
+ break;
357
+ }
358
+ }
359
+ }
360
+ } else {
361
+ $rebuild_prep = TRUE;
362
+ }
363
+
364
+ /* Convert any integer Page/Post/Attachment ID to a string
365
+ so it will match the type of a Query value in PHP/HTTP
366
+ */
367
+ if ( isset( $url_array['id'] ) && is_int( $url_array['id'] ) ) {
368
+ $settings[ $url_type ][ $index ]['id'] = ( string ) $url_array['id'];
369
+ jr_mt_messages( 'Integer type Page/Post/Attachment ID found: converted to String type' );
370
+ }
371
+ if ( isset( $url_array['id_kw'] )
372
+ && ( ( !is_string( $url_array['id_kw'] ) )
373
+ || ( !in_array( $url_array['id_kw'], array( 'page_id', 'p', 'attachment_id' ), TRUE ) ) ) ) {
374
+ unset( $settings[ $url_type ][ $index ]['id_kw'] );
375
+ }
376
+ if ( isset( $url_array['rel_url'] )
377
+ && ( !is_string( $url_array['rel_url'] ) ) ) {
378
+ unset( $settings[ $url_type ][ $index ]['rel_url'] );
379
+ }
380
  }
 
 
381
  }
382
  }
383
  }
384
  }
385
+ /* Check ['query']
386
+ */
387
+ if ( ( !isset( $settings['query'] ) ) || ( !is_array( $settings['query'] ) ) ) {
388
+ $settings['query'] = $default_settings['query'];
389
+ jr_mt_messages( 'Query setting(s) deleted because they are corrupt' );
390
+ } else {
391
+ foreach ( $settings['query'] as $keyword => $value_array ) {
392
+ if ( is_array( $value_array ) ) {
393
+ foreach ( $value_array as $value => $theme ) {
394
+ if ( ( !is_string( $theme ) )
395
+ || ( !isset( $jr_mt_all_themes[ $theme ] ) ) ) {
396
+ unset( $settings['query'][ $keyword ][ $value ] );
397
+ jr_mt_messages( 'Query setting deleted: either it was corrupt or specified Theme that no longer exists' );
398
+ /* All the checking for Empty parents (e.g. - $settings['query'][ $keyword ])
399
+ and matching remember/query elements is done later.
400
+ */
401
+ }
402
+ }
403
+ if ( empty( $settings['query'][ $keyword ] ) ) {
404
+ unset( $settings['query'][ $keyword ] );
405
+ }
406
+ } else {
407
+ unset( $settings['query'][ $keyword ] );
408
+ jr_mt_messages( 'Query setting deleted because it is corrupt' );
409
+ }
410
+ }
411
+ /* Check: 'remember', 'override'
412
+ */
413
+ foreach ( array( 'remember', 'override' ) as $key ) {
414
+ if ( is_array( $settings[ $key ] )
415
+ && isset( $settings[ $key ]['query'] )
416
+ && is_array( $settings[ $key ]['query'] ) ) {
417
+ foreach ( $settings[ $key ] as $query_constant => $query_array ) {
418
+ if ( 'query' !== $query_constant ) {
419
+ unset( $settings[ $key ][ $query_constant ] );
420
+ jr_mt_messages( 'Sticky/Override setting(s) deleted because they are corrupt' );
421
+ }
422
+ }
423
+ foreach ( $settings[ $key ]['query'] as $keyword => $value_array ) {
424
+ if ( is_array( $value_array ) ) {
425
+ foreach ( $value_array as $value => $bool ) {
426
+ if ( ( !is_bool( $bool ) )
427
+ || ( !isset( $settings['query'][ $keyword ][ $value ] ) ) ) {
428
+ unset( $settings[ $key ]['query'][ $keyword ][ $value ] );
429
+ jr_mt_messages( 'Sticky/Override setting(s) deleted because they are corrupt' );
430
+ }
431
+ }
432
+ if ( empty( $settings[ $key ]['query'][ $keyword ] ) ) {
433
+ unset( $settings[ $key ]['query'][ $keyword ] );
434
+ }
435
+ } else {
436
+ unset( $settings[ $key ]['query'][ $keyword ] );
437
+ jr_mt_messages( 'Sticky/Override setting(s) deleted because they are corrupt' );
438
+ }
439
+ }
440
+ } else {
441
+ $settings[ $key ] = $default_settings[ $key ];
442
+ jr_mt_messages( 'Sticky/Override setting(s) deleted because they are corrupt' );
443
+ }
444
+ }
445
+ }
446
+
447
+ /* Check for missing ['rel_url'] and build it
448
+ */
449
+ $settings = jr_mt_missing_rel_url( $settings, JR_MT_HOME_URL );
450
+
451
+ /* Check if Site URL has changed by comparing corresponding ['url'] of ['home']
452
+ setting in Aliases array with current Site URL.
453
+ */
454
+ $site_url_changed = FALSE;
455
+ if ( is_array( $settings['aliases'] ) ) {
456
+ foreach ( $settings['aliases'] as $index => $alias ) {
457
+ if ( $alias['home'] ) {
458
+ if ( !jr_mt_same_url( $alias['prep'], JR_MT_HOME_URL ) ) {
459
+ /* Site URL has changed.
460
+ */
461
+ $site_url_changed = TRUE;
462
+ $old_site_url = $alias['url'];
463
+ break;
464
+ }
465
+ }
466
+ }
467
+ if ( $site_url_changed ) {
468
+ $settings = jr_mt_rebuild_display_url( $settings, $old_site_url );
469
+
470
+ /* See if there is an Alias entry for the new Site URL.
471
+ If not, add one, and perhaps another with/without www.
472
+ */
473
+ $settings = jr_mt_rebuild_alias_home( $settings );
474
+
475
+ jr_mt_messages( 'Site Address (URL) has changed: any URLs and Aliases in settings have been updated' );
476
+
477
+ /* Rebuild ['prep']
478
+ */
479
+ $rebuild_prep = TRUE;
480
+ }
481
+ } else {
482
+ $settings['aliases'] = jr_mt_init_aliases();
483
+ jr_mt_messages( 'No Site Aliases defined; set to Default Aliases, if any' );
484
+ }
485
+
486
+ /* Rebuild all ['prep'] entries, if required.
487
+ */
488
+ if ( isset( $rebuild_prep ) ) {
489
+ $settings = jr_mt_rebuild_prep( $settings );
490
+ jr_mt_messages( 'URL settings, if any, have had their URL matching structures rebuilt' );
491
+ }
492
+ } else {
493
+ $settings = jr_mt_default_settings();
494
+ jr_mt_messages( 'First use (or after plugin deleted): initialize Plugin Settings', 'immediate' );
495
+ }
496
+ if ( $settings !== $settings_original ) {
497
+ if ( update_option( 'jr_mt_settings', $settings ) ) {
498
+ jr_mt_messages( 'Plugin Settings have changed and were successfully updated', 'immediate' );
499
+ } else {
500
+ jr_mt_messages( 'Plugin Settings have changed but could not be updated', 'immediate' );
501
+ }
502
+ }
503
+ jr_mt_messages( NULL, 'display' );
504
+ jr_mt_messages( 'Check complete', 'immediate' );
505
+ ?>
506
+ </ul>
507
+ <p>
508
+ While every attempt has been made,
509
+ in the Settings Check above,
510
+ to ensure that the plugin's
511
+ Setting are valid,
512
+ if you experience any unexpected behaviour,
513
+ you should try to re-create the Settings from scratch.
514
+ First, re-initialize all Settings to their defaults,
515
+ by deactivating, deleting, installing and reactivating this plugin;
516
+ then visit this Settings page again,
517
+ as this is where the Settings are initialized.
518
+ </p>
519
+ <?php
520
+ jr_mt_admin_init();
521
+
522
+ echo '<form action="options.php" method="POST">';
523
+ $permalink = get_option( 'permalink_structure' );
524
+ if ( isset( $internal_settings['permalink'] ) ) {
525
+ if ( $internal_settings['permalink'] !== $permalink ) {
526
+ /* Permalink Structure has been changed.
527
+ */
528
+ if ( empty( $settings['url'] ) && empty( $settings['url_prefix'] ) && empty( $settings['url_asterisk'] ) ) {
529
+ $update = TRUE;
530
+ } else {
531
+ ?>
532
+ <p>
533
+ Permalink Structure has been changed.
534
+ In the
535
+ <b>
536
+ Current Theme Selection Entries
537
+ </b>
538
+ Section just below,
539
+ please review all
540
+ URL=,
541
+ URL Prefix=
542
+ and
543
+ URL Prefix*=
544
+ entries,
545
+ as they may need to be changed to reflect the new Permalink Structure.
546
+ <br />
547
+ <input type="checkbox" id="permalink" name="jr_mt_settings[permalink]" value="true" />
548
+ Dismiss Warning
549
+ </p>
550
+ <?php
551
+ $update = FALSE;
552
+ }
553
+ } else {
554
+ $update = FALSE;
555
+ }
556
+ } else {
557
+ /* Permalink Internal Setting for Plugin not set,
558
+ so initialize it to current Permalink Structure.
559
+ */
560
+ $update = TRUE;
561
  }
562
+ if ( $update ) {
563
+ $internal_settings['permalink'] = $permalink;
564
+ update_option( 'jr_mt_internal_settings', $internal_settings );
565
+ }
566
+ ?>
567
+ <h3>Overview</h3>
568
+ <p>This Plugin allows you to selectively display Themes on your web site
569
+ other than the Theme shown as
570
+ <b>
571
+ Active
572
+ </b>
573
+ on
574
+ <b>
575
+ Appearance-Themes
576
+ </b>
577
+ in the WordPress Admin panels.
578
+ </p>
579
+ <p>
580
+ Below,
581
+ Theme Selection entries can be created
582
+ where each Entry specifies which of the installed themes shown on the Appearance-Themes Admin panel will be applied to:
583
+ <ul class="jrmtpoints">
584
+ <li>The Site Home</li>
585
+ <li>An exact URL of any non-Admin page on this WordPress Site</li>
586
+ <li>One or more URLs that begin with the partial URL you specify ("URL Prefix")</li>
587
+ <li>One or more URLs that begin with the wildcard URL you specify ("URL Prefix*")</li>
588
+ <li>Any URL containing a Specific Query Keyword (<code>?keyword</code> or <code>&keyword</code>)</li>
589
+ <li>Any URL containing a Specific Query Keyword/Value pair (<code>?keyword=value</code> or <code>&keyword=value</code>)</li>
590
+ <li>For the same site visitor, all non-Admin pages after a <b>Sticky</b> Query Keyword/Value pair is specified in any URL (Advanced Settings tab)</li>
591
+ <li>AJAX URLs containing <code>admin-ajax.php</code> (Advanced Settings tab)</li>
592
+ <li>All Pages (Advanced Settings tab)</li>
593
+ <li>All Posts (Advanced Settings tab)</li>
594
+ <li>Everything else, except what is specified above (Advanced Settings tab)</li>
595
+ </ul>
596
+ </p>
597
+ <h3>Important Notes</h3>
598
+ <?php
599
+ if ( function_exists('is_multisite') && is_multisite() ) {
600
+ echo "In a WordPress Network (AKA Multisite), Themes must be <b>Network Enabled</b> before they will appear as Available Themes on individual sites' Appearance-Themes panel.";
601
+ }
602
+ echo '<p>';
603
+ echo "The Active Theme, defined to WordPress in the Appearance-Themes admin panel, is <b>$theme</b>.";
604
+ if ( trim( $settings['current'] ) ) {
605
+ echo " But it is being overridden by the Theme for Everything setting (see Advanced Settings tab), which set the plugin's default Theme to <b>";
606
+ echo wp_get_theme( $settings['current'] )->Name;
607
+ echo '</b>. You will not normally need to specify this default Theme in any of the other Settings on this page, though you will need to specify the WordPress Active Theme wherever you want it to appear. Or, if you specify, on the Advanced Settings tab, a different Theme for All Pages, All Posts or Everything, and wish to use the default Theme for one or more specific Pages, Posts or other non-Admin pages.';
608
+ } else {
609
+ echo ' You will not normally need to specify it in any of the Settings on this page. The only exception would be if you specify, on the Advanced Settings tab, a different Theme for All Pages, All Posts or Everything, and wish to use the Active Theme for one or more specific Pages, Posts or other non-Admin pages.';
610
+ }
611
+ echo '</p>';
612
+
613
+ if ( jr_mt_plugin_update_available() ) {
614
+ echo '<p>A new version of this Plugin (' . $jr_mt_plugin_data['Name'] . ') is available from the WordPress Repository.'
615
+ . ' Updating as quickly as possible is strongly recommend because new versions fix problems that users like you have already reported.'
616
+ . ' <a class="thickbox" title="' . $jr_mt_plugin_data['Name'] . '" href="' . network_admin_url()
617
+ . 'plugin-install.php?tab=plugin-information&plugin=' . $jr_mt_plugin_data['slug']
618
+ . '&section=changelog&TB_iframe=true&width=640&height=768">Click here</a> for more details.</p>';
619
+ }
620
+ ?>
621
+ <p>
622
+ If a newly-added Theme Selection does not seem to be working,
623
+ especially if the associated web page does not display properly,
624
+ try deactivating any plugins that provide Caching.
625
+ You may find that you have to flush the plugin's Cache whenever you add or change a Theme Selection setting.
626
+ Also note that some Caching plugins only cache for visitors who are not logged in,
627
+ so be sure to check your site after logging out.
628
+ </p>
629
+ <p>
630
+ Need more help?
631
+ Please click on the
632
+ <a href="#" onClick="jrMtTabs( 6, 6 );">Help tab</a>
633
+ above
634
+ for more information.
635
+ </p>
636
+ <hr />
637
+ <?php
638
+
639
+ // Plugin Settings are displayed and entered here:
640
+ settings_fields( 'jr_mt_settings' );
641
+ do_settings_sections( 'jr_mt_settings_page' );
642
+ ?>
643
+ <p>
644
+ More comprehensive AJAX support is planned for future Versions of this plugin.
645
+ </p>
646
+ <p>
647
+ &nbsp;
648
+ </p>
649
+ <p>
650
+ <input name="jr_mt_settings[tab3]" type="submit" value="Save All Changes" class="button-primary" />
651
+ </p>
652
+ </form>
653
+ <?php
654
  }
 
655
 
 
 
 
 
 
 
 
656
  ?>
657
+ </div>
658
+ <div id="jr-mt-settings4" style="display: none;">
659
+ <h3>
660
+ Theme Options and Template Selection
661
+ </h3>
662
  <p>
663
+ This tab provides information on changing Theme Options
664
+ (Widgets, Sidebars, Menus, Background, Header, etc.)
665
+ for all the different Themes used on a WordPress site.
666
+ </p>
667
+ <p>
668
+ Information on changing the Template for each Page or Post
669
+ is found near the bottom of this tab.
670
+ </p>
671
+ <h3>
672
+ Changing Theme Options
673
+ </h3>
674
  <p>
675
+ For the Active Theme, nothing changes when using the jonradio Multiple Themes plugin.
676
+ Options for the Active Theme,
677
+ including Widgets, Sidebars, Menus, Background, Header and other Customizations supported by the Theme,
678
+ can be modified in the Admin panel using the Appearance menu items on the left sidebar.
679
+ Some Themes also provide their own menu items in the left sidebar of the Admin panel,
680
+ and these will still appear for the Active Theme when using this plugin.
681
  </p>
682
+ <p>
683
+ It is more difficult to modify Options for installed Themes that are not the WordPress Active Theme.
684
+ Building this functionality into this plugin is in the plans for a future Version,
685
+ but it is not clear just how practical that is, so the best that can be said is:
686
+ <i>
687
+ Maybe</i>.
688
  </p>
689
+ <p>
690
+ For now, there are four approaches that can be used to change Options for an installed Theme that is not the Active Theme.
691
+ The first works best if only one Theme has a lot of Options that need to be changed frequently:
692
+ </p>
693
+ <ol>
694
+ <li>
695
+ Make that Theme the Active Theme defined in the Appearance-Themes WordPress admin panel;
696
+ </li>
697
+ <li>
698
+ If that meant changing the Active Theme,
699
+ the previous Active Theme can be selected on the plugin's
700
+ <b>
701
+ Advanced Settings
702
+ </b>
703
+ tab
704
+ in the
705
+ <b>
706
+ Select Theme for Everything
707
+ </b>
708
+ field
709
+ and it will be used everywhere except where you have specified
710
+ another Theme in the Theme Selection entries for this plugin.
711
+ </li>
712
+ </ol>
713
+ <p>
714
+ For other situations,
715
+ two multi-step Methods are available,
716
+ and are described in the two Sections below.
717
+ Both Methods work for most Theme Options,
718
+ with the following exceptions:
719
+ </p>
720
+ <ol>
721
+ <li>
722
+ Menus really work well with Method #1,
723
+ but are severely restricted with Method #2;
724
+ </li>
725
+ <li>
726
+ Widgets normally only work with Method #2;
727
+ </li>
728
+ <li>
729
+ Using both Methods may cause conflicts;
730
+ </li>
731
+ <li>
732
+ No matter which Method you choose,
733
+ you may lose previously-set Theme Options.
734
+ A Backup and Recovery of your WordPress Database
735
+ would be required to avoid such a loss.
736
+ </li>
737
+ </ol>
738
+ <p>
739
+ Finally, there is the Method of Last Resort.
740
+ Although it is the most obvious way to change Theme Options,
741
+ it is also the most risky,
742
+ in terms of loss of Options set for other Themes.
743
+ </p>
744
+ <h4>
745
+ <u>
746
+ Method #1</u>:
747
+ Set the Theme Options with Live Preview.
748
+ </h4>
749
+ <p>
750
+ Note: Widgets cannot be placed using this Method.
751
+ </p>
752
+ <ol>
753
+ <li>
754
+ Go to Appearance-Themes in the WordPress Admin panels.
755
+ </li>
756
+ <li>
757
+ Mouse over the Theme that you wish to change
758
+ and click the Live Preview button that appears.
759
+ </li>
760
+ <li>
761
+ Use the left sidebar to modify the Theme Options.
762
+ Note that
763
+ <b>
764
+ Navigation
765
+ </b>
766
+ will not appear in the Live Preview sidebar until a Menu has been defined in Appearance-Menus.
767
+ Navigation is where you would set the custom menu(s) to be used for the Theme you are currently previewing.
768
+ </li>
769
+ <li>
770
+ Click the Save & Activate button.
771
+ </li>
772
+ <li>
773
+ Go immediately to Appearance-Themes in the WordPress Admin panels.
774
+ </li>
775
+ <li>
776
+ Mouse over the Theme that had previously been the Active Theme
777
+ and click the Activate button that appears
778
+ to reactivate the Active Theme.
779
+ </li>
780
+ </ol>
781
+ <h4>
782
+ <u>
783
+ Method #2</u>:
784
+ Use the Theme Test Drive plugin.
785
+ </h4>
786
+ <p>
787
+ Note: this approach only allows Menus to be set for one Theme. Using this method to assign one or more menus to a Theme will unassign menus for all other Themes.
788
+ </p>
789
+ <p>
790
+ The jonradio Multiple Themes plugin (i.e. - this plugin) must be Deactivated,
791
+ and the Theme Test Drive plugin installed and activated.
792
+ This enables each Theme to be selected with the Theme Test Drive plugin,
793
+ allowing the Theme's Options to be set
794
+ <i>
795
+ as if
796
+ </i>
797
+ it were the Active Theme.
798
+ </p>
799
+ <ol>
800
+ <li>
801
+ Deactivate the jonradio Multiple Themes plugin.
802
+ </li>
803
+ <li>
804
+ Install the Theme Test Drive plugin found at
805
+ <a target="_blank" href="http://wordpress.org/plugins/theme-test-drive/">http://wordpress.org/plugins/theme-test-drive/</a>.
806
+ </li>
807
+ <li>
808
+ Activate the Theme Test Drive plugin.
809
+ </li>
810
+ <li>
811
+ Go to
812
+ <b>
813
+ Appearance-Theme Test Drive
814
+ </b>
815
+ in the WordPress Admin panels.
816
+ </li>
817
+ <li>
818
+ In the Usage section, select a Theme whose Options you wish to change.
819
+ </li>
820
+ <li>
821
+ Push the Enable Theme Drive button at the bottom of the Admin panel.
822
+ </li>
823
+ <li>
824
+ Make your changes to the Theme Options, including Widgets, Sidebars, Menus (see note above about Menus), Background, Header and other Customizations for this alternate Theme
825
+ using the Appearance submenu
826
+ in the WordPress Admin panels,
827
+ just as you would for the Active Theme.
828
+ </li>
829
+ <li>
830
+ If more than one Theme has Options that need changing, repeat Steps 4-8 for each Theme
831
+ (except the Active Theme,
832
+ which should be only changed
833
+ <i>
834
+ without
835
+ </i>
836
+ the Theme Test Drive plugin activated).
837
+ </li>
838
+ <li>
839
+ Deactivate the Theme Test Drive plugin.
840
+ </li>
841
+ <li>
842
+ Activate this plugin (jonradio Multiple Themes).
843
+ </li>
844
+ <li>
845
+ Changes to the Options for the Active Theme can now be made normally, just as you would without either plugin.
846
+ </li>
847
+ <li>
848
+ Both the alternate and Active Themes should now display all Theme options properly when selected through the jonradio Multiple Themes plugin.
849
+ </li>
850
+ </ol>
851
+ <h4>
852
+ <u>
853
+ Method of Last Resort</u>:
854
+ Activate a Theme to change its Options.
855
+ </h4>
856
+ <p>
857
+ Note:
858
+ this approach is the most likely to cause the loss of Theme Options set in other Themes,
859
+ though the risk does depend on the Theme and the Options that are set.
860
+ </p>
861
+ <ol>
862
+ <li>
863
+ Go to Appearance-Themes in the WordPress Admin panels.
864
+ </li>
865
+ <li>
866
+ Mouse over the Theme that you wish to change
867
+ and click the Activate button that appears.
868
+ </li>
869
+ <li>
870
+ Make the appropriate changes to Theme Options,
871
+ clicking a Save button, if present
872
+ (some Options are automatically saved; some are not).
873
+ </li>
874
+ <li>
875
+ Go immediately to Appearance-Themes in the WordPress Admin panels.
876
+ </li>
877
+ <li>
878
+ Mouse over the Theme that had previously been the Active Theme
879
+ and click the Activate button that appears
880
+ to reactivate the Active Theme.
881
+ </li>
882
+ </ol>
883
+ <h3>
884
+ Changing Templates
885
+ </h3>
886
+ <p>
887
+ Many Themes provide more than one Template.
888
+ For each Page or Post, you can select the Template you want to use for that Page or Post.
889
+ </p>
890
+ <p>
891
+ For the Active Theme, nothing changes when using the jonradio Multiple Themes plugin.
892
+ Select an alternate Template from the drop-down list in the Template field of the Page Attributes section of the Add New Page, Edit Page, Add New Post or Edit Post page of the Admin panels.
893
+ Or the Template field in Quick Edit.
894
+ </p>
895
+ <p>
896
+ It is more difficult to change Templates for Pages or Posts defined with the jonradio Multiple Themes plugin to use Installed Themes that are not the Active Theme.
897
+ Building this functionality into this plugin is in the plans for a future Version.
898
+ </p>
899
+ <p>
900
+ Use the Theme Test Drive plugin.
901
+ The jonradio Multiple Themes plugin (i.e. - this plugin) must be Deactivated, and the Theme Test Drive plugin installed and activated,
902
+ so that each Theme can be selected with the Theme Test Drive plugin,
903
+ allowing the Theme's Template to be set for each Page or Post using that Theme
904
+ <i>
905
+ as if
906
+ </i>
907
+ it were the Active Theme.
908
+ </p>
909
+ <ol>
910
+ <li>
911
+ Deactivate the jonradio Multiple Themes plugin.
912
+ </li>
913
+ <li>
914
+ Install the Theme Test Drive plugin found at
915
+ <a target="_blank" href="http://wordpress.org/plugins/theme-test-drive/">http://wordpress.org/plugins/theme-test-drive/</a>.
916
+ </li>
917
+ <li>
918
+ Activate the Theme Test Drive plugin.
919
+ </li>
920
+ <li>
921
+ Go to
922
+ <b>
923
+ Appearance-Theme Test Drive
924
+ </b>
925
+ in the WordPress Admin panels.
926
+ </li>
927
+ <li>
928
+ In the Usage section, select a Theme whose Templates need to be changed for a Post or Page.
929
+ </li>
930
+ <li>
931
+ Push the Enable Theme Drive button at the bottom of the Admin panel.
932
+ </li>
933
+ <li>
934
+ Go to Posts-All Posts or Pages-All Pages in the WordPress Admin panels.
935
+ </li>
936
+ <li>
937
+ For each Page or Post where a Template needs to be changed for this Theme,
938
+ mouse over the Page or Post title and click on Quick Edit.
939
+ </li>
940
+ <li>
941
+ Change the Template field.
942
+ </li>
943
+ <li>
944
+ Click the Update button.
945
+ </li>
946
+ <li>
947
+ Repeat Steps 8-10 for each Page or Post that requires a change to Template for this Theme.
948
+ </li>
949
+ <li>
950
+ If more than one Theme has Pages or Posts with Templates that need to be changed,
951
+ repeat Steps 4-11 for each Theme
952
+ (except the Active Theme,
953
+ where Template changes should only be made
954
+ <i>
955
+ without
956
+ </i>
957
+ the Theme Test Drive plugin activated).
958
+ </li>
959
+ <li>
960
+ Deactivate the Theme Test Drive plugin.
961
+ </li>
962
+ <li>
963
+ Activate this plugin (jonradio Multiple Themes).
964
+ </li>
965
+ <li>
966
+ Changing Templates for the Active Theme can now be made normally, just as you would without either plugin.
967
+ </li>
968
+ <li>
969
+ Both the alternate and Active Themes should now display the correct Template when selected through the jonradio Multiple Themes plugin.
970
+ </li>
971
+ </ol>
972
+ </div>
973
+ <div id="jr-mt-settings5" style="display: none;">
974
+ <h3>
975
+ System Information
976
+ </h3>
977
+ <p>
978
+ WordPress DEBUG mode is currently turned
979
  <?php
980
+ if ( TRUE === WP_DEBUG ) {
981
+ echo 'on';
982
+ } else {
983
+ echo 'off';
 
 
 
 
 
 
 
 
 
 
984
  }
985
+ echo ". It is controlled by the <code>define('WP_DEBUG', true);</code> statement near the bottom of <code>"
986
+ . ABSPATH
987
+ . 'wp-config.php</code></p>';
988
+ $posix = function_exists( 'posix_uname' );
989
+ echo '<p>You are currently running:<ul class="jrmtpoints">'
990
+ . "<li>The {$jr_mt_plugin_data['Name']} plugin Version {$jr_mt_plugin_data['Version']}</li>"
991
+ . '<ul class="jrmtpoints">' . "<li>The Path to the plugin's directory is <code>" . rtrim( jr_mt_path(), '/' ) . '</code></li>'
992
+ . "<li>The URL to the plugin's directory is <code>" . plugins_url() . "/{$jr_mt_plugin_data['slug']}</code></li></ul>"
993
+ . "<li>The Active Theme is $theme Version $theme_version</li>"
994
+ . '<ul class="jrmtpoints">'
995
+ . "<li>The Path to the Active Theme's stylesheet directory is <code>" . get_stylesheet_directory() . '</code></li>'
996
+ . "<li>The Path to the Active Theme's template directory is <code>" . get_template_directory() . '</code></li></ul>'
997
+ . '<li>Site Address (URL) is <code>' . JR_MT_HOME_URL . '</code></li>'
998
+ . '<li>WordPress Address (URL) is <code>' . site_url() . '</code></li>';
999
+ $permalink = get_option( 'permalink_structure' );
1000
+ if ( empty( $permalink ) ) {
1001
+ $permalink = 'Default (Query <code>/?p=123</code>)';
1002
  } else {
1003
+ $permalink = "<code>$permalink</code>";
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1004
  }
1005
+ echo "<li>The current Permalink Structure is $permalink";
1006
+ echo "<li>WordPress Version $current_wp_version</li>";
1007
+ echo '<ul class="jrmtpoints"><li>WordPress language is set to ' , get_bloginfo( 'language' ) . '</li></ul>';
1008
+ echo '<li>' . php_uname( 's' ) . ' operating system, Release/Version ' . php_uname( 'r' ) . ' / ' . php_uname( 'v' ) . '</li>';
1009
+ if ( $posix ) {
1010
+ $array = posix_getpwuid( posix_getuid() );
1011
+ $user = $array['name'];
1012
+ echo "<li>Real operating system User ID that runs WordPress is $user</li>";
1013
+ $array = posix_getpwuid( posix_geteuid() );
1014
+ $user = $array['name'];
1015
+ echo "<li>Effective operating system User ID that runs WordPress is $user</li>";
1016
  }
1017
+ echo '<li>' . php_uname( 'm' ) . ' computer hardware</li>';
1018
+ echo '<li>Host name ' . php_uname( 'n' ) . '</li>';
1019
+ echo '<li>php Version ' . phpversion() . '</li>';
1020
+ echo '<ul class="jrmtpoints"><li>php memory_limit ' . ini_get('memory_limit') . '</li>';
1021
+ if ( !$posix ) {
1022
+ echo '<li>POSIX functions are not available</li>';
1023
+ }
1024
+ echo '</ul><li>Zend engine Version ' . zend_version() . '</li>';
1025
+ echo '<li>Web Server software is ' . getenv( 'SERVER_SOFTWARE' ) . '</li>';
1026
+ if ( function_exists( 'apache_get_version' ) && ( FALSE !== $apache = apache_get_version() ) ) {
1027
+ echo '<ul class="jrmtpoints"><li>Apache Version' . "$apache</li></ul>";
1028
+ }
1029
+ global $wpdb;
1030
+ echo '<li>MySQL Version ' . $wpdb->get_var( 'SELECT VERSION();', 0, 0 ) . '</li>';
 
 
 
 
 
 
 
 
 
 
1031
 
1032
+ echo '</ul></p>';
1033
+
1034
+ $paths = array(
1035
+ '/..',
1036
+ '/',
1037
+ '/wp-content/',
1038
+ '/wp-content/plugins/',
1039
+ '/wp-content/plugins/' . dirname( jr_mt_plugin_basename() ),
1040
+ '/wp-content/plugins/' . dirname( jr_mt_plugin_basename() ) . '/readme.txt'
1041
+ );
1042
+ echo '<h3>File Permissions</h3><p>All of the Paths shown below are relative to the WordPress Site Path <code>'
1043
+ . ABSPATH
1044
+ . '</code><br />The first ("/..") is the Parent Directory <code>'
1045
+ . dirname( ABSPATH )
1046
+ . '/</code> and the second ("/") is the WordPress Site Path itself.</p><table class="widefat"><thead><tr><th>Path</th><th>Type</th><th>Read</th><th>Write</th>';
1047
+ if ( $posix ) {
1048
+ echo '<th>Owner</th><th>Group</th>';
1049
  }
1050
+ echo '</tr></thead><tbody>';
1051
+ foreach ( $paths as $path ) {
1052
+ $full_path = ABSPATH . jr_mt_substr( $path, 1 );
1053
+ if ( is_dir( $full_path ) ) {
1054
+ $type = 'Directory';
1055
+ } else {
1056
+ $type = 'File';
1057
  }
1058
+ if ( is_readable( $full_path ) ) {
1059
+ $read = 'Yes';
1060
  } else {
1061
+ $read = 'No';
1062
  }
1063
+ if ( is_writeable( $full_path ) ) {
1064
+ $write = 'Yes';
1065
+ } else {
1066
+ $write = 'No';
1067
+ }
1068
+ if ( $posix ) {
1069
+ if ( FALSE === ( $uid = fileowner( $full_path ) ) ) {
1070
+ $user = '-';
1071
+ $group = '-';
1072
+ } else {
1073
+ $array = posix_getpwuid( $uid );
1074
+ $user = $array['name'];
1075
+ $array = posix_getgrgid( filegroup( $full_path ) );
1076
+ $group = $array['name'];
1077
+ }
1078
+ }
1079
+ echo "<tr><td>$path</td><td>$type</td><td>$read</td><td>$write</td>";
1080
+ if ( $posix ) {
1081
+ echo "<td>$user</td><td>$group</td>";
1082
+ }
1083
+ echo '<tr>';
1084
  }
1085
+ echo '</tbody></table>';
1086
+ ?>
1087
+ </div>
1088
+ <div id="jr-mt-settings6" style="display: none;">
1089
+ <h3>
1090
+ If Any Theme Uses AJAX
1091
+ </h3>
1092
+ <p>
1093
+ More and more Themes,
1094
+ especially Paid Themes,
1095
+ use AJAX,
1096
+ which adds impressive-looking dynamic features to a web site.
1097
+ </p>
1098
+ <p>
1099
+ AJAX also adds complexity.
1100
+ Instead of a single web page having a single URL,
1101
+ AJAX uses additional URLs to dynamically insert content into a web page after it is initially displayed.
1102
+ </p>
1103
+ <p>
1104
+ Each of those URLs must be considered when creating
1105
+ Theme Selection settings for this plugin.
1106
+ Otherwise,
1107
+ this plugin will return the incorrect Theme for some portions of
1108
+ a web page,
1109
+ which may cause the
1110
+ display of incorrect content,
1111
+ or no content at all.
1112
+ </p>
1113
+ <p>
1114
+ Version 7.1 of this plugin introduced an AJAX Advanced Setting
1115
+ for URLs that include
1116
+ <code>admin-ajax.php</code>,
1117
+ a common AJAX technique in WordPress.
1118
+ Additional AJAX support is planned for future versions of this plugin,
1119
+ as well as a Diagnostic Tool for determining URLs being used by AJAX,
1120
+ most likely as a separate plugin.
1121
+ </p>
1122
+ <h3>
1123
+ An Alternative to This Plugin
1124
+ </h3>
1125
+ <p>
1126
+ WordPress was not designed with the idea in mind of multiple Themes on a single Site.
1127
+ Which is why this plugin struggles to provide full multi-theme capabilities.
1128
+ </p>
1129
+ <p>
1130
+ An alternative to this plugin
1131
+ is a
1132
+ <a href="http://codex.wordpress.org/Create_A_Network">WordPress Network</a>,
1133
+ also known as Multisite.
1134
+ Each WordPress Site within a WordPress Network can have a different Theme.
1135
+ WordPress was built to fully support Multiple Themes used in this way.
1136
+ </p>
1137
+ <p>
1138
+ What is less obvious,
1139
+ is that a WordPress Network of Sites
1140
+ can be designed to appear as if it is a single integrated web site.
1141
+ For example,
1142
+ using the Subdirectory option of a WordPress Network:
1143
+ </p>
1144
+ <ol>
1145
+ <li>
1146
+ Site 1 could be
1147
+ <code>example.com</code>,
1148
+ the web site's home page,
1149
+ and any other web pages with the same Theme;
1150
+ </li>
1151
+ <li>
1152
+ Site 2 could be
1153
+ <code>example.com/forum</code>,
1154
+ the discussion forum portion of your web site
1155
+ with a different Theme;
1156
+ </li>
1157
+ <li>
1158
+ Site 3 could be
1159
+ <code>example.com/news</code>
1160
+ for a News section with its own Theme;
1161
+ and
1162
+ </li>
1163
+ <li>
1164
+ Site 4 could be
1165
+ <code>example.com/store</code>
1166
+ with a fourth Theme for a Store.
1167
+ </li>
1168
+ </ol>
1169
+ <p>
1170
+ Admittedly,
1171
+ extra effort will be required to make a WordPress Network look like a single web site,
1172
+ especially if you rely on automatically-created Menus.
1173
+ Menu entries will have to be manually created to point to other Sites within the WordPress Network.
1174
+ </p>
1175
+ <h3>
1176
+ Need Help?
1177
+ </h3>
1178
+ <p>
1179
+ Need help with this plugin?
1180
+ Check the
1181
+ <a href="#" onClick="jrMtTabs( 4, 6 );">Theme Options</a>
1182
+ and
1183
+ <a href="#" onClick="jrMtTabs( 5, 6 );">System Information</a>
1184
+ tabs above,
1185
+ and the
1186
+ <a target="_blank" href="http://wordpress.org/plugins/jonradio-multiple-themes/">Description</a>,
1187
+ <a target="_blank" href="http://wordpress.org/plugins/jonradio-multiple-themes/faq/">FAQ</a>,
1188
+ <a target="_blank" href="http://wordpress.org/plugins/jonradio-multiple-themes/installation/">Installation</a>
1189
+ and
1190
+ <a target="_blank" href="http://wordpress.org/support/plugin/jonradio-multiple-themes">Support</a>
1191
+ tabs
1192
+ in the <a target="_blank" href="http://wordpress.org/plugins/jonradio-multiple-themes/">WordPress Directory entry for this plugin</a>.
1193
+ All of this information is based on the many support questions that jonradio has answered both on-line and via e-mail since this plugin was first released in 2012.
1194
+ </p>
1195
+ <p>
1196
+ Please be sure to check them all out if you have any unanswered questions.
1197
+ If you cannot find the answers to all of your questions there,
1198
+ simply post your question in the
1199
+ <a target="_blank" href="http://wordpress.org/support/plugin/jonradio-multiple-themes">Support Forum</a>
1200
+ or
1201
+ <a target="_blank" href="http://zatzlabs.com/contact-us/">contact jonradio directly</a>.
1202
+ </p>
1203
+ <p>
1204
+ For information on other jonradio plugins,
1205
+ including Contact and Donation information,
1206
+ <a target="_blank" href="http://zatzlabs.com/plugins/">click here</a>.
1207
+ </p>
1208
+ <h3>
1209
+ Want to Help?
1210
+ </h3>
1211
+ <p>
1212
+ As well as <a target="_blank" href="http://zatzlabs.com/plugins/">Donations</a>,
1213
+ you can also help by
1214
+ <a target="_blank" href="http://wordpress.org/support/view/plugin-reviews/jonradio-multiple-themes">Reviewing this plugin</a>
1215
+ for the WordPress Plugin Directory,
1216
+ and telling other people that it works for your particular combination of Plugin version and WordPress version
1217
+ in the Compability section of the
1218
+ <a target="_blank" href="http://wordpress.org/plugins/jonradio-multiple-themes/">WordPress Directory entry for this plugin</a>.
1219
+ </p>
1220
+ </div>
1221
+
1222
+ </div>
1223
+ <?php
1224
+ /* </div> ends the <div class="wrap"> at the beginning
1225
+ */
1226
  }
1227
 
1228
+ require_once( jr_mt_path() . 'includes/admin-sections.php' );
1229
+ require_once( jr_mt_path() . 'includes/admin-validate.php' );
1230
+
1231
  ?>
includes/debug/debug.php DELETED
@@ -1,36 +0,0 @@
1
- <?php
2
- /* require_once( jr_mt_path() . 'includes/debug/debug.php' );
3
- jr_dump( 'jr_mt_validate_settings $input', $input );
4
- */
5
-
6
- function jr_dump( $comment, $dump_var ) {
7
- $file_name = 'jonradio-dump.txt';
8
-
9
- $header = '***' . current_time('mysql') . ': ' . $_SERVER['SERVER_NAME'] . $_SERVER['REQUEST_URI'];
10
- ob_start();;
11
- echo "$comment: ";
12
- var_dump( $dump_var );
13
- $output = ob_get_clean() . jr_dump_env();
14
- if ( function_exists('is_multisite') && is_multisite() ) {
15
- global $site_id, $blog_id;
16
- $file_name = $site_id . '-' . $blog_id . '-' . $file_name;
17
- }
18
- $file = fopen( plugin_dir_path( __FILE__ ) . $file_name, 'at' );
19
- fwrite( $file, $header . PHP_EOL . $output );
20
- fclose( $file );
21
-
22
- return;
23
- }
24
-
25
- function jr_dump_env() {
26
- global $jr_dump_env_first;
27
- if ( isset( $jr_dump_env_first ) ) {
28
- $output = '';
29
- } else {
30
- $jr_dump_env_first = FALSE;
31
- $output = PHP_EOL;
32
-
33
- }
34
- return $output;
35
- }
36
- ?>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
includes/functions.php CHANGED
@@ -1,4 +1,171 @@
1
  <?php
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2
  /**
3
  * Return WordPress Current Theme, as defined in Appearance Admin panels
4
  *
@@ -13,156 +180,526 @@ function jr_mt_current_theme( $option ) {
13
  }
14
 
15
  /**
16
- * Given URL, return post or page ID, if possible, and relative path if not
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
17
  *
18
- * Calls jr_mt_query_keywords.
19
  *
20
- * @param string $url full URL of WordPress page, post, admin, etc.
21
- * @return array array with keys of "type", "id" and "page_url":
22
- * string type "pages", "posts" or "admin"
23
- * string id Page ID or Post ID or FALSE
24
- * string page_url relative URL WordPress page, post, admin, etc. or FALSE
25
- * string rel_url URL relative to WordPress home
26
- * bool home is URL Site Home?
27
  */
28
- function jr_mt_url_to_id( $url_orig ) {
29
- // Some hosts, likely only IIS, insert an erroneous "/index.php" into the middle of the Permalink in $_SERVER['REQUEST_URI']
30
- $url = str_replace( '/index.php', '', $url_orig );
31
-
32
- $trim = '\ /'; // remove leading and trailing backslashes, blanks and forward slashes
 
 
 
 
33
 
34
- $is_home = FALSE;
35
-
36
- // get_home_url() returns "https://subdomain.domain.com/wp" - the full URL of the home page of the site
37
- $home = trim( parse_url( get_home_url(), PHP_URL_PATH ), $trim ); // "wp"
38
-
39
- $admin_home = trim( parse_url( admin_url(), PHP_URL_PATH ), $trim );
40
- $page_url = trim( parse_url( $url, PHP_URL_PATH ), $trim ); // "wp/fruit/apples"
41
- $is_admin = ( $admin_home == substr( $page_url, 0, strlen( $admin_home ) ) );
42
- if ( !empty( $home ) ) { // Only if WordPress is installed in a subfolder, NOT in the Root
43
- $page_url = trim( substr( $page_url, stripos( $page_url, $home ) + strlen( $home ) ), $trim ); // "fruit/apples"
 
 
 
44
  }
45
- $rel_url = $page_url;
46
-
47
- $type = FALSE;
48
-
49
- $id = jr_mt_query_keywords( parse_url( $url, PHP_URL_QUERY ) );
50
- if ( $id === NULL ) {
51
- if ( $is_admin ) {
52
- $id = FALSE;
53
- $type = 'admin';
54
- } else {
55
- // Check for home page (url_to_postid() does not work for home page)
56
- if ( empty( $page_url ) ) {
57
- $is_home = TRUE;
58
- $id = get_option('page_on_front');
59
- if ( $id == 0 ) {
60
- // There is no home Page; posts are displayed instead on the home page
61
- $page_url = '';
62
- $id = FALSE;
63
- } else {
64
- $type = 'pages';
65
- }
66
- } else {
67
- global $wp_rewrite;
68
- if ( is_null( $wp_rewrite ) ) {
69
- $GLOBALS['wp_rewrite'] = new WP_Rewrite();
70
- }
71
- global $wp;
72
- if ( is_null( $wp ) ) {
73
- $GLOBALS['jr_mt_cache'] = FALSE;
74
- $wp = (object) array( 'public_query_vars' => array() );
75
  } else {
76
- if ( !isset( $wp->public_query_vars ) ) {
77
- $GLOBALS['jr_mt_cache'] = FALSE;
78
- $wp->public_query_vars = array();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
79
  }
 
80
  }
81
- $id = url_to_postid( $url );
82
- if ( $id == 0 ) {
83
- $id = FALSE;
 
 
 
 
84
  } else {
85
- $post_obj = get_post( $id );
86
- if ( $post_obj->post_type == 'page' ) {
87
- $type = 'pages';
88
- } else {
89
- if ( $post_obj->post_type == 'post' ) {
90
- $type = 'posts';
91
- }
92
- }
93
  }
94
  }
 
 
 
 
 
95
  }
96
  } else {
97
- // id in query of URL (?keyword=value&keyword=value)
98
- $type = key( $id );
99
- $id = $id[$type];
100
- $page_url = FALSE;
 
 
 
 
 
101
  }
102
- return array(
103
- 'type' => $type,
104
- 'id' => $id,
105
- 'page_url' => $page_url,
106
- 'rel_url' => $rel_url,
107
- 'home' => $is_home
108
- );
109
  }
110
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
111
  /**
112
- * Return page_id= or p= (post ID) or page= (admin page) value from a URL
113
  *
114
- * Calls parse_str function in its own variable space because it could create virtually any variable name!
115
- * Only looks at page_id=, p= and page= now, but could be expanded to other query keywords.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
116
  *
117
- * @param string $url_query Query portion (after the ?) in a URL
118
- * @return var array with key of "pages", "posts" or "admin" and value of page_id=, p= or page=, respectively; or NULL if none are present
119
  */
120
- function jr_mt_query_keywords( $url_query ) {
121
- if ( $url_query === NULL ) {
122
- return NULL;
123
- } else {
124
- parse_str( $url_query );
125
- if ( isset( $page_id ) ) {
126
- return array( 'pages' => $page_id );
127
  } else {
128
- if ( isset( $p ) ) {
129
- return array( 'posts' => $p );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
130
  } else {
131
- if ( isset( $page ) ) {
132
- return array( 'admin' => $page );
133
- } else {
134
- if ( isset( $cat ) ) {
135
- return array( 'cat' => $cat );
136
- } else {
137
- if ( isset( $m ) ) {
138
- return array( 'archive' => $m );
139
- } else {
140
- return NULL;
141
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
142
  }
 
 
 
143
  }
144
  }
 
 
 
145
  }
146
  }
 
147
  }
148
 
149
- /**
150
- * Is the URL on the current WordPress web site?
151
- *
152
- * Checks if URL begins with Site Home URL.
153
- *
154
- * @param string $url URL to be checked to be sure it is "on" the current WordPress web site
155
- * @return var bool TRUE if URL on current WordPress web site; string error message otherwise
156
- */
157
- function jr_mt_site_url( $url ) {
158
- $check_url = trim( $url );
159
- if ( strcasecmp( 'http', substr( $check_url, 0, 4 ) ) != 0 ) {
160
- return 'URL does not begin with http://';
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
161
  }
162
- $site_home = get_home_url();
163
- if ( strcasecmp( $site_home, substr( $check_url, 0, strlen( $site_home ) ) ) != 0 ) {
164
- return "URL specified is not part of current WordPress web site. URL must begin with '$site_home'";
 
 
 
 
 
 
165
  }
166
- return TRUE;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
167
  }
 
168
  ?>
1
  <?php
2
+
3
+ /* Exit if .php file accessed directly
4
+ */
5
+ if ( !defined( 'ABSPATH' ) ) {
6
+ exit;
7
+ }
8
+
9
+ global $jr_mt_path;
10
+ $jr_mt_path = plugin_dir_path( JR_MT_FILE );
11
+ /**
12
+ * Return Plugin's full directory path with trailing slash
13
+ *
14
+ * Local XAMPP install might return:
15
+ * C:\xampp\htdocs\wpbeta\wp-content\plugins\jonradio-multiple-themes/
16
+ *
17
+ */
18
+ function jr_mt_path() {
19
+ global $jr_mt_path;
20
+ return $jr_mt_path;
21
+ }
22
+
23
+ global $jr_mt_plugin_basename;
24
+ $jr_mt_plugin_basename = plugin_basename( JR_MT_FILE );
25
+ /**
26
+ * Return Plugin's Basename
27
+ *
28
+ * For this plugin, it would be:
29
+ * jonradio-multiple-themes/jonradio-multiple-themes.php
30
+ *
31
+ */
32
+ function jr_mt_plugin_basename() {
33
+ global $jr_mt_plugin_basename;
34
+ return $jr_mt_plugin_basename;
35
+ }
36
+
37
+ if ( !function_exists( 'get_plugin_data' ) ) {
38
+ require_once( ABSPATH . 'wp-admin/includes/plugin.php' );
39
+ }
40
+
41
+ global $jr_mt_plugin_data;
42
+ $jr_mt_plugin_data = get_plugin_data( JR_MT_FILE );
43
+ $jr_mt_plugin_data['slug'] = basename( dirname( JR_MT_FILE ) );
44
+
45
+ global $jr_mt_options_cache;
46
+ $all_options = wp_load_alloptions();
47
+ $jr_mt_options_cache['stylesheet'] = $all_options['stylesheet'];
48
+ $jr_mt_options_cache['template'] = $all_options['template'];
49
+
50
+ /* Handle this Odd Situation:
51
+ For WordPress 4.0 and all previous versions,
52
+ wp_get_themes() returns array() when this plugin is Network Activated.
53
+ Waiting until Action 'plugins_loaded' overcomes this problem,
54
+ but potentially creates other problems.
55
+ */
56
+ if ( is_plugin_active_for_network( $jr_mt_plugin_basename ) ) {
57
+ add_action( JR_MT_WP_GET_THEMES_ACTION, 'jr_mt_wp_get_themes_fix', JR_MT_RUN_FIRST );
58
+ function jr_mt_wp_get_themes_fix() {
59
+ DEFINE( 'JR_MT_WP_GET_THEMES_WORKS', TRUE );
60
+ /* Force the next request for Stylesheet or Template
61
+ to process the Theme Selection logic,
62
+ even if previous requests have cached the Theme.
63
+ */
64
+ unset( $GLOBALS['jr_mt_theme'] );
65
+ if ( is_admin() ) {
66
+ global $jr_mt_all_themes_cache;
67
+ $jr_mt_all_themes_cache = wp_get_themes();
68
+ update_option( 'jr_mt_all_themes', $jr_mt_all_themes_cache );
69
+ }
70
+ }
71
+ } else {
72
+ DEFINE( 'JR_MT_WP_GET_THEMES_WORKS', TRUE );
73
+ }
74
+ function jr_mt_all_themes() {
75
+ if ( defined( 'JR_MT_WP_GET_THEMES_WORKS' ) ) {
76
+ global $jr_mt_all_themes_cache;
77
+ if ( isset( $jr_mt_all_themes_cache ) ) {
78
+ $return = $jr_mt_all_themes_cache;
79
+ } else {
80
+ $return = wp_get_themes();
81
+ }
82
+ } else {
83
+ /* Probably not valid,
84
+ typically empty array.
85
+ Better to store and retrieve from Settings myself.
86
+ */
87
+ if ( FALSE === ( $return = get_option( 'jr_mt_all_themes' ) ) ) {
88
+ $return = wp_get_themes();
89
+ }
90
+ }
91
+ return $return;
92
+ }
93
+
94
+ /**
95
+ * Check for missing Settings and set them to defaults
96
+ *
97
+ * Ensures that the Named Setting exists, and populates it with defaults for any missing values.
98
+ * Safe to use on every execution of a plugin because it only does an expensive Database Write
99
+ * when it finds missing Settings.
100
+ *
101
+ * Does not delete any key not found in $defaults.
102
+ *
103
+ * @param string $name Name of Settings as looked up with get_option()
104
+ * @param array $defaults Each default Settings value in [key] => value format
105
+ * @return bool/Null Return value from update_option(), or NULL if update_option() not called
106
+ */
107
+ function jr_mt_missing_settings( $name, $defaults ) {
108
+ $updated = FALSE;
109
+ if ( FALSE === ( $settings = get_option( $name ) ) ) {
110
+ $settings = $defaults;
111
+ $updated = TRUE;
112
+ } else {
113
+ foreach ( $defaults as $key => $value ) {
114
+ if ( !isset( $settings[$key] ) ) {
115
+ $settings[$key] = $value;
116
+ $updated = TRUE;
117
+ }
118
+ }
119
+ }
120
+ if ( $updated ) {
121
+ $return = update_option( $name, $settings );
122
+ } else {
123
+ $return = NULL;
124
+ }
125
+ return $return;
126
+ }
127
+
128
+ /* As well as dealing with the low probability that a single mb_ function has been disabled in a php.ini,
129
+ this also supports older versions of PHP as mb_ functions were introduced one by one over a number of php versions.
130
+ */
131
+ if ( function_exists( 'mb_substr' ) ) {
132
+ function jr_mt_substr() {
133
+ $args = func_get_args();
134
+ if ( isset( $args[2] ) ) {
135
+ return mb_substr( $args[0], $args[1], $args[2] );
136
+ } else {
137
+ return mb_substr( $args[0], $args[1] );
138
+ }
139
+ }
140
+ } else {
141
+ function jr_mt_substr() {
142
+ $args = func_get_args();
143
+ if ( isset( $args[2] ) ) {
144
+ return substr( $args[0], $args[1], $args[2] );
145
+ } else {
146
+ return substr( $args[0], $args[1] );
147
+ }
148
+ }
149
+ }
150
+ if ( function_exists( 'mb_strlen' ) ) {
151
+ function jr_mt_strlen( $string ) {
152
+ return mb_strlen( $string );
153
+ }
154
+ } else {
155
+ function jr_mt_strlen( $string ) {
156
+ return strlen( $string );
157
+ }
158
+ }
159
+ if ( function_exists( 'mb_strtolower' ) ) {
160
+ function jr_mt_strtolower( $string ) {
161
+ return mb_strtolower( $string );
162
+ }
163
+ } else {
164
+ function jr_mt_strtolower( $string ) {
165
+ return strtolower( $string );
166
+ }
167
+ }
168
+
169
  /**
170
  * Return WordPress Current Theme, as defined in Appearance Admin panels
171
  *
180
  }
181
 
182
  /**
183
+ * What Themes are defined to Plugin?
184
+ *
185
+ * @return arr - a list of Themes (folder names) defined in Settings of Plugin, plus Active WordPress Theme
186
+ **/
187
+ function jr_mt_themes_defined() {
188
+ $themes = array( jr_mt_current_theme( 'stylesheet' ), jr_mt_current_theme( 'template' ) );
189
+ $settings = get_option( 'jr_mt_settings' );
190
+ foreach ( $settings as $key => $value ) {
191
+ switch ( $key ) {
192
+ case 'url':
193
+ case 'url_prefix':
194
+ case 'url_asterisk':
195
+ foreach ( $value as $arr ) {
196
+ $themes[] = $arr['theme'];
197
+ }
198
+ break;
199
+ case 'query':
200
+ foreach ( $value as $keyword => $arr1 ) {
201
+ foreach ( $arr1 as $value => $theme ) {
202
+ $themes[] = $theme;
203
+ }
204
+ }
205
+ break;
206
+ case 'all_pages':
207
+ case 'all_posts':
208
+ case 'site_home':
209
+ case 'current':
210
+ if ( !empty( $value ) ) {
211
+ $themes[] = $value;
212
+ }
213
+ break;
214
+ }
215
+ }
216
+ return array_unique( $themes );
217
+ }
218
+
219
+ /**
220
+ * Do two URLs point at the same location on a web site?
221
  *
222
+ * Preps URL, if string
223
  *
224
+ * @param string/array $url1 URL to compare, a string, or an array in special format created by companion function
225
+ * @param string/array $url2 URL to compare, a string, or an array in special format created by companion function
226
+ * @return bool bool TRUE if URL matches prefix; FALSE otherwise
 
 
 
 
227
  */
228
+ function jr_mt_same_url( $url1, $url2 ) {
229
+ if ( is_string( $url1 ) ) {
230
+ $url1 = jr_mt_prep_url( $url1 );
231
+ }
232
+ if ( is_string( $url2 ) ) {
233
+ $url2 = jr_mt_prep_url( $url2 );
234
+ }
235
+ return ( $url1 == $url2 );
236
+ }
237
 
238
+ /**
239
+ * Does a specified Prefix URL match the given URL?
240
+ *
241
+ * Preps URL, if string.
242
+ * Note: parameters MUST be in the right order
243
+ *
244
+ * @param string/array $prefix front part of a URL to compare, a string, or an array in special format created by companion function
245
+ * @param string/array $url full URL to compare, a string, or an array in special format created by companion function
246
+ * @return bool bool TRUE if Prefix matches first part of URL; FALSE otherwise
247
+ */
248
+ function jr_mt_same_prefix_url( $prefix, $url ) {
249
+ if ( is_string( $prefix ) ) {
250
+ $prefix = jr_mt_prep_url( $prefix );
251
  }
252
+ if ( is_string( $url ) ) {
253
+ $url = jr_mt_prep_url( $url );
254
+ }
255
+ if ( $url['host'] === $prefix['host'] ) {
256
+ if ( $url['port'] === $prefix['port'] ) {
257
+ if ( $url['path'] === $prefix['path'] ) {
258
+ /* Host and Path both exactly match for URL and Prefix specified.
259
+ */
260
+ if ( array() === $prefix['query'] ) {
261
+ $match = TRUE;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
262
  } else {
263
+ /* Now the hard part: determining a legitimate prefix match for Query
264
+ */
265
+ foreach ( $prefix['query'] as $prefix_keyword => $prefix_value_array ) {
266
+ foreach ( $prefix_value_array as $prefix_value => $prefix_equalsign ) {
267
+ $one_match = FALSE;
268
+ foreach ( $url['query'] as $url_keyword => $url_value_array ) {
269
+ foreach( $url_value_array as $url_value => $url_equalsign ) {
270
+ if ( jr_mt_substr( $url_keyword, 0, jr_mt_strlen( $prefix_keyword ) ) === ( string ) $prefix_keyword ) {
271
+ if ( $prefix_equalsign ) {
272
+ if ( $url_equalsign ) {
273
+ if ( jr_mt_substr( $url_value, 0, jr_mt_strlen( $prefix_value ) ) === ( string ) $prefix_value ) {
274
+ $one_match = TRUE;
275
+ }
276
+ }
277
+ } else {
278
+ $one_match = TRUE;
279
+ }
280
+ }
281
+ }
282
+ }
283
+ }
284
+ /* All Prefix Queries must match.
285
+ */
286
+ if ( FALSE === $one_match ) {
287
+ return FALSE;
288
+ }
289
  }
290
+ $match = TRUE;
291
  }
292
+ } else {
293
+ /* Paths must exactly match if Prefix specifies Query
294
+ */
295
+ if ( array() === $prefix['query'] ) {
296
+ /* No Query in Prefix, so check Path for Prefix match
297
+ */
298
+ $match = ( $prefix['path'] === jr_mt_substr( $url['path'], 0, jr_mt_strlen( $prefix['path'] ) ) );
299
  } else {
300
+ $match = FALSE;
 
 
 
 
 
 
 
301
  }
302
  }
303
+ } else {
304
+ /* Perhaps unnecessary restriction:
305
+ If Hosts match, then so much Ports.
306
+ */
307
+ $match = FALSE;
308
  }
309
  } else {
310
+ if ( ( 0 === $prefix['port'] ) && ( '' === $prefix['path'] ) && ( array() === $prefix['query'] ) ) {
311
+ /* No Path or Query in Prefix, so check Host for Prefix match
312
+ */
313
+ $match = ( $prefix['host'] === jr_mt_substr( $url['host'], 0, jr_mt_strlen( $prefix['host'] ) ) );
314
+ } else {
315
+ /* Hosts must exactly match if Prefix specifies Path or Query
316
+ */
317
+ $match = FALSE;
318
+ }
319
  }
320
+ return $match;
 
 
 
 
 
 
321
  }
322
 
323
+ function jr_mt_same_prefix_url_asterisk( $prefix, $url ) {
324
+ if ( is_string( $prefix ) ) {
325
+ $prefix = jr_mt_prep_url( $prefix );
326
+ }
327
+ if ( is_string( $url ) ) {
328
+ $url = jr_mt_prep_url( $url );
329
+ }
330
+ $path_prefix = explode( '/', $prefix['path'] );
331
+ $path_url = explode( '/', $url['path'] );
332
+ foreach ( $path_prefix as $i => $directory ) {
333
+ if ( '*' === $directory ) {
334
+ $path_url[ $i ] = '*';
335
+ }
336
+ }
337
+ $url['path'] = implode( '/', $path_url );
338
+ return jr_mt_same_prefix_url( $prefix, $url );
339
+ }
340
+
341
  /**
342
+ * Standardize a URL into an array of values that can be accurately compared with another
343
  *
344
+ * Preps URL, by removing any UTF Left-to-right Mark (LRM), usually found as a suffix,
345
+ * translating the URL to lower-case, removing prefix http[s]//:,
346
+ * any embedded index.php and any trailing slash or #bookmark,
347
+ * and breaks up ?keyword=value queries into array elements.
348
+ *
349
+ * Structure/Elements of Array returned:
350
+ * [host] - domain.com - all subdomains, including www., are included
351
+ * [path] - dir/file.ext
352
+ * [query] - any Queries (e.g. - "?kw=val&kw2=val2") broken up as follows:
353
+ * [$keyword] => [$value] => $equalsign
354
+ * $value - blank if not present
355
+ * $equalsign - bool indicating if = was present in URL
356
+ * Format prior to Version 7.0:
357
+ * [$keyword] => $value with preceding equals sign, only if equals sign was present
358
+ * To simplify processing of this Array, zero length strings and empty arrays are used,
359
+ * rather than NULL entries or missing array elements.
360
  *
361
+ * @param string $url URL to create an array from, in special format for accurate comparison
362
+ * @return array array of standardized attributes of the URL (see structure above)
363
  */
364
+ function jr_mt_prep_url( $url ) {
365
+ /* Handle troublesome %E2%80%8E UTF Left-to-right Mark (LRM) suffix first.
366
+ */
367
+ if ( FALSE === strpos( $url, '%E2%80%8E' ) ) {
368
+ if ( FALSE === strpos( rawurlencode( $url ), '%E2%80%8E' ) ) {
369
+ $url_clean = $url;
 
370
  } else {
371
+ $url_clean = rawurldecode( str_replace( '%E2%80%8E', '', rawurlencode( $url ) ) );
372
+ /* mb_str_replace() does not exist because str_replace() is binary-safe.
373
+ */
374
+ }
375
+ } else {
376
+ $url_clean = str_replace( '%E2%80%8E', '', $url );
377
+ }
378
+ $url_clean = str_replace( '\\', '/', trim( $url_clean ) );
379
+
380
+ /* parse_url(), especially before php Version 5.4.7,
381
+ has a history of problems when Scheme is not present,
382
+ especially for LocalHost as a Host,
383
+ so add a prefix of http:// if :// is not found
384
+ */
385
+ if ( FALSE === strpos( $url_clean, '://' ) ) {
386
+ $url_clean = "http://$url_clean";
387
+ }
388
+
389
+ $parse_array = parse_url( jr_mt_strtolower( $url_clean ) );
390
+ /* Get rid of URL components that do not matter to us in our comparison of URLs
391
+ */
392
+ foreach ( array( 'scheme', 'user', 'pass', 'fragment' ) as $component ) {
393
+ unset ( $parse_array[ $component ] );
394
+ }
395
+ /* Remove standard HTTP Port 80 and HTTPS Port 443, if present.
396
+ */
397
+ $parse_array['port'] = jr_mt_non_default_port( $parse_array, 'port' );
398
+ if ( isset( $parse_array['path'] ) ) {
399
+ /* Remove any index.php occurences in path, since these can be spurious in IIS
400
+ and perhaps other environments.
401
+ */
402
+ $parse_array['path'] = str_replace( 'index.php', '', $parse_array['path'] );
403
+ /* Remove leading and trailing slashes from path
404
+ */
405
+ $parse_array['path'] = rtrim( $parse_array['path'], "/\\" );
406
+ } else {
407
+ $parse_array['path'] = '';
408
+ }
409
+ /* Take /?keyword=value&keyword=value URL query parameters
410
+ and break them up into array( keyword => value => equals?, keyword => value => equals? )
411
+ */
412
+ if ( isset( $parse_array['query'] ) ) {
413
+ $parms = explode( '&', $parse_array['query'] );
414
+ $parse_array['query'] = array();
415
+ foreach( $parms as $parm ) {
416
+ if ( FALSE === strpos( $parm, '=' ) ) {
417
+ $parse_array['query'][ $parm ][''] = FALSE;
418
  } else {
419
+ $kwv = explode( '=', $parm );
420
+ $parse_array['query'][ $kwv[0] ][ $kwv[1] ] = TRUE;
421
+ }
422
+ /* Remember the presence of the Equals Sign ("=") in each Query
423
+ to differentiate between a URL Prefix with a Query Keyword followed by
424
+ an Equals Sign, and one without. For example, "address" would match
425
+ address2=abc, while "address=" would not.
426
+ */
427
+ }
428
+ } else {
429
+ $parse_array['query'] = array();
430
+ }
431
+ return $parse_array;
432
+ }
433
+
434
+ global $jr_mt_default_ports;
435
+ $jr_mt_default_ports = array( 80, 443 );
436
+ function jr_mt_non_default_port( $array, $key ) {
437
+ /* Remove standard HTTP Port 80 and HTTPS Port 443, if present.
438
+ */
439
+ global $jr_mt_default_ports;
440
+ if ( empty( $array[ $key ] ) || in_array( $array[ $key ], $jr_mt_default_ports ) ) {
441
+ $port = 0;
442
+ } else {
443
+ $port = $array[ $key ];
444
+ }
445
+ return $port;
446
+ }
447
+
448
+ /** Build Query Array
449
+
450
+ $array[keyword] = array( value, value, ... )
451
+ Sets both keyword and value to lower-case as
452
+ that is how they are stored in Settings.
453
+
454
+ Supports only & separator, not proposed semi-colon separator.
455
+
456
+ Handles duplicate keywords in all four of these forms:
457
+ kw=val1&kw=val2 kw[]=val1&kw[]=val2 kw=val1&kw=val1 kw[]=val1&kw[]=val1
458
+ but nothing else, e.g. - kw=val1,val2 is not valid;
459
+ it returns "val1,val2" as the Value.
460
+ Also handles kw1&kw2
461
+
462
+ Tests of parse_str() in PHP 5.5.9 proved that semi-colon and comma
463
+ are not supported. But, neither is kw=val1,kw=val2 which is why
464
+ this function is written without the use of parse_str.
465
+ */
466
+ function jr_mt_query_array() {
467
+ /* Remove array entry indicators ("[]") as we properly handle duplicate keywords,
468
+ and covert to lower-case for comparison purposes.
469
+ */
470
+ $queries = array();
471
+ if ( !empty( $_SERVER['QUERY_STRING'] ) ) {
472
+ $query = explode( '&', jr_mt_strtolower( str_replace( '[]', '', $_SERVER['QUERY_STRING'] ) ) );
473
+ foreach ( $query as $kwval ) {
474
+ $query_entry = explode( '=', $kwval );
475
+ if ( !isset( $query_entry[1] ) ) {
476
+ $query_entry[1] = '';
477
+ }
478
+ $queries[ $query_entry[0] ][] = $query_entry[1];
479
+ }
480
+ }
481
+ return $queries;
482
+ }
483
+
484
+ /* Check for numeric IP Addresse, both IPv4 and IPv6
485
+ */
486
+ function jr_mt_is_ip( $domain_name ) {
487
+ if ( FALSE !== strpos( $domain_name, ':' ) ) {
488
+ /* IPv6
489
+ */
490
+ $return = TRUE;
491
+ } else {
492
+ if ( 4 === count( $ip_array = explode( '.', $domain_name ) ) ) {
493
+ foreach ( $ip_array as $ip ) {
494
+ if ( ctype_digit( $ip ) ) {
495
+ /* IPv4: maximum = 255
496
+ */
497
+ if ( $ip > 255 ) {
498
+ $return = FALSE;
499
+ break;
500
  }
501
+ } else {
502
+ $return = FALSE;
503
+ break;
504
  }
505
  }
506
+ $return = !isset( $return );
507
+ } else {
508
+ $return = FALSE;
509
  }
510
  }
511
+ return $return;
512
  }
513
 
514
+ /* Initialize the Aliases array in the Settings.
515
+
516
+ First entry will be the Site Address (URL) field value from WordPress General Settings.
517
+ Most of the time, Create an Alias of that URL,
518
+ based on adding or removing www. in the domain name.
519
+ Including Subdomains, which do not normally have www. defined
520
+ as an Alias, but you never know!
521
+ But not for numeric IP addresses, or localhost.
522
+
523
+ Returns an array containing one or two arrays, each in this format:
524
+ ['url'] => URL
525
+ ['prep'] => URL array created by jr_mt_prep_url()
526
+ ['home'] => TRUE if this is Site Address (URL) field value from WordPress General Settings,
527
+ which is stored here to determine when the WordPress General Setting is changed.
528
+ */
529
+ function jr_mt_init_aliases() {
530
+ $return = array(
531
+ array(
532
+ 'url' => JR_MT_HOME_URL,
533
+ 'prep' => jr_mt_prep_url( JR_MT_HOME_URL ),
534
+ 'home' => TRUE
535
+ )
536
+ );
537
+
538
+ if ( FALSE !== ( $url_parsed = parse_url( JR_MT_HOME_URL ) ) ) {
539
+ $host = $url_parsed['host'];
540
+ if ( 0 !== strcasecmp( $host, 'localhost' ) ) {
541
+ /* Check for numeric IP Addresse, both IPv4 and IPv6
542
+ */
543
+ if ( !jr_mt_is_ip( $host ) ) {
544
+ if ( 0 === strncasecmp( $host, 'www.', 4 ) ) {
545
+ $url_parsed['host'] = jr_mt_substr( $host, 4 );
546
+ } else {
547
+ $url_parsed['host'] = 'www.' . $host;
548
+ }
549
+ $url = jr_mt_unparse_url( $url_parsed );
550
+ $return[] = array(
551
+ 'url' => $url,
552
+ 'prep' => jr_mt_prep_url( $url ),
553
+ 'home' => FALSE
554
+ );
555
+ }
556
+ }
557
+ }
558
+ return $return;
559
+ }
560
+
561
+ function jr_mt_unparse_url( $parse_array ) {
562
+ if ( function_exists( 'http_build_url' ) ) {
563
+ $url = http_build_url( '', $parse_array );
564
+ } else {
565
+ /* From: https://github.com/jakeasmith/http_build_url
566
+ Version: 0.1.3
567
+ Version created about July 2014, retrieved November 4, 2014
568
+ */
569
+ $url = $parse_array['scheme'] . '://';
570
+
571
+ if ( isset( $parse_array['user'] ) ) {
572
+ $url .= $parse_array['user'];
573
+
574
+ if ( isset( $parse_array['pass'] ) ) {
575
+ $url .= ':' . $parse_array['pass'];
576
+ }
577
+
578
+ $url .= '@';
579
+ }
580
+
581
+ if ( isset( $parse_array['host'] ) ) {
582
+ $url .= $parse_array['host'];
583
+ }
584
+
585
+ if ( isset( $parse_array['port'] ) ) {
586
+ $url .= ':' . $parse_array['port'];
587
+ }
588
+
589
+ if ( !empty( $parse_array['path'] ) ) {
590
+ $url .= $parse_array['path'];
591
+ }
592
+
593
+ if ( isset( $parse_array['query'] ) ) {
594
+ $url .= '?' . $parse_array['query'];
595
+ }
596
+
597
+ if ( isset( $parse_array['fragment'] ) ) {
598
+ $url .= '#' . $parse_array['fragment'];
599
+ }
600
+ }
601
+ return $url;
602
+ }
603
+
604
+ /* Given a URL and a list of Site Aliases,
605
+ either as strings or in "prep format" (arrays),
606
+ return either:
607
+ - (string) the first Site Alias that matches;
608
+ - (string) the relative URL, relative to the Site Alias; and
609
+ - (array) the relative URL in "prep format"
610
+ OR
611
+ - FALSE on failure.
612
+ */
613
+ function jr_mt_make_relative( $url, $aliases ) {
614
+ if ( is_string( $url ) ) {
615
+ $url = jr_mt_prep_url( $url );
616
+ }
617
+ $return = FALSE;
618
+ foreach ( $aliases as $alias ) {
619
+ if ( jr_mt_same_prefix_url( $alias, $url ) ) {
620
+ $return = array(
621
+ 'alias' => $alias,
622
+ 'rel_url' => $rel_url,
623
+ 'rel_url_prep' => $rel_url_prep
624
+ );
625
+ break;
626
+ }
627
+ }
628
+ return $return;
629
+ }
630
+
631
+ /* Which Site Alias is the "Best Match"?
632
+
633
+ We already know that more than one Site Alias matches
634
+ all of the current URL for the full length of the Site Alias.
635
+ For example, if example.com and example.com/wp both matched,
636
+ example.com/wp would be the "best" match, in the sense of longest match.
637
+
638
+ $alias_array - in settings['alias'] format
639
+ $matches - array of keys to $alias_array, of matching Aliases
640
+ return - key of best match
641
+ */
642
+ function jr_mt_best_match_alias( $alias_array, $matches ) {
643
+ /* For each component, if they differ,
644
+ Best is determined as follows, in the following order:
645
+ Host - longest string is Best
646
+ Port - non-zero is Best
647
+ Path - longest string is Best.
648
+ */
649
+ $best = $matches;
650
+ $max = -1;
651
+ foreach ( $best as $key ) {
652
+ $len = strlen( $alias_array[ $key ]['prep']['host'] );
653
+ if ( $len > $max ) {
654
+ $max = $len;
655
+ }
656
+ }
657
+ foreach ( $best as $index => $key ) {
658
+ if ( $max > strlen( $alias_array[ $key ]['prep']['host'] ) ) {
659
+ unset ( $best[ $index ] );
660
+ }
661
  }
662
+ foreach ( $best as $key ) {
663
+ if ( 0 !== $alias_array[ $key ]['prep']['port'] ) {
664
+ foreach ( $best as $index => $key ) {
665
+ if ( 0 === $alias_array[ $key ]['prep']['port'] ) {
666
+ unset( $best[ $index ] );
667
+ }
668
+ }
669
+ break;
670
+ }
671
  }
672
+ $max = -1;
673
+ foreach ( $best as $key ) {
674
+ if ( empty( $alias_array[ $key ]['prep']['path'] ) ) {
675
+ $len = 0;
676
+ } else {
677
+ $len = strlen( $alias_array[ $key ]['prep']['path'] );
678
+ }
679
+ if ( $len > $max ) {
680
+ $max = $len;
681
+ }
682
+ }
683
+ foreach ( $best as $index => $key ) {
684
+ if ( empty( $alias_array[ $key ]['prep']['path'] ) ) {
685
+ $len = 0;
686
+ } else {
687
+ $len = strlen( $alias_array[ $key ]['prep']['path'] );
688
+ }
689
+ if ( $max > $len ) {
690
+ unset ( $best[ $index ] );
691
+ }
692
+ }
693
+ /* If there is more than one Site Alias left
694
+ in the $best array, then it should mean
695
+ there are duplicate entries,
696
+ but that makes no sense.
697
+ So, just return the first one in the array.
698
+
699
+ reset() returns the first array element,
700
+ not the key.
701
+ */
702
+ return reset( $best );
703
  }
704
+
705
  ?>
includes/index.html ADDED
File without changes
includes/old-wp.php ADDED
@@ -0,0 +1,24 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /* Exit if .php file accessed directly
4
+ */
5
+ if ( !defined( 'ABSPATH' ) ) {
6
+ exit;
7
+ }
8
+
9
+ /* A Version of WordPress older than the first one supported by the Plugin
10
+ is being run.
11
+ */
12
+
13
+ add_action( 'all_admin_notices', 'jr_mt_all_admin_notice' );
14
+ // Runs after admin_menu hook
15
+ add_action( 'admin_notices', 'jr_mt_all_admin_notice' ); // for older versions
16
+
17
+ function jr_mt_all_admin_notice() {
18
+ // Only displayed in Admin panels:
19
+ echo '<div class="error">Deactivated the <b>jonradio Multiple Themes</b> plugin: requires WordPress Version 3.4 or newer; you are running Version '
20
+ . get_bloginfo( 'version' ) . '</div>';
21
+ deactivate_plugins( JR_MT_FILE );
22
+ }
23
+
24
+ ?>
includes/select-theme.php CHANGED
@@ -1,9 +1,100 @@
1
  <?php
2
- // Select the relevant Theme
 
 
 
 
3
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4
  add_filter( 'pre_option_stylesheet', 'jr_mt_stylesheet' );
5
  add_filter( 'pre_option_template', 'jr_mt_template' );
6
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
7
  function jr_mt_stylesheet() {
8
  return jr_mt_theme( 'stylesheet' );
9
  }
@@ -25,103 +116,469 @@ function jr_mt_theme( $option ) {
25
  These three different values for each Theme must be clearly separated, as all three usually
26
  match, but do not have to, e.g. - Child Themes.
27
  */
28
- $GLOBALS['jr_mt_cache'] = TRUE;
29
  global $jr_mt_theme;
30
  if ( !isset( $jr_mt_theme ) ) {
31
  $jr_mt_theme = array();
32
  }
33
  if ( !isset( $jr_mt_theme[$option] ) ) {
34
  $theme = jr_mt_chosen();
35
- if ( $theme === FALSE ) {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
36
  // Get both at once, to save a repeat of this logic later:
37
  $jr_mt_theme['stylesheet'] = jr_mt_current_theme( 'stylesheet' );
38
  $jr_mt_theme['template'] = jr_mt_current_theme( 'template' );
39
  } else {
40
- $themes = wp_get_themes();
41
- $jr_mt_theme['stylesheet'] = $themes[$theme]->stylesheet;
42
- $jr_mt_theme['template'] = $themes[$theme]->template;
 
 
43
  }
44
  }
45
  $theme = $jr_mt_theme[$option];
46
- global $jr_mt_cache;
47
- if ( $jr_mt_cache === FALSE ) {
48
- unset( $jr_mt_theme[$option] );
49
- }
50
  return $theme;
51
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
52
 
53
- // Returns FALSE for Current Theme
54
- function jr_mt_chosen() {
55
- if ( is_admin() ) {
56
- // Admin panel
57
- // return P2 theme if p2ajax= is present; current theme otherwise
58
- parse_str( $_SERVER['QUERY_STRING'], $keywords );
59
- if ( isset( $keywords['p2ajax'] ) && array_key_exists( 'p2', wp_get_themes() ) ) {
60
- $theme = 'p2';
61
- } else {
62
- $theme = FALSE; // Current Theme
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
63
  }
 
64
  } else {
65
- // Non-Admin page, i.e. - Public Site, etc.
66
- extract( jr_mt_url_to_id( 'http://' . $_SERVER['SERVER_NAME'] . $_SERVER['REQUEST_URI'] ) );
67
- $settings = get_option( 'jr_mt_settings' );
68
- if ( $home ) {
69
- if ( trim( $settings['site_home'] ) != '' ) {
70
- return $settings['site_home'];
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
71
  }
72
  }
73
- $ids = $settings['ids'];
74
- if ( $id === FALSE ) {
75
- if ( isset( $ids[$page_url] ) ) {
76
- $theme = $ids[$page_url]['theme'];
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
77
  } else {
78
- $theme = jr_mt_check_all( $type, $rel_url, $ids );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
79
  }
80
  } else {
81
- if ( isset( $ids[$id] ) ) {
82
- $theme = $ids[$id]['theme'];
83
- } else {
84
- $theme = jr_mt_check_all( $type, $rel_url, $ids );
 
 
 
 
 
 
 
 
 
85
  }
86
  }
87
  }
88
- return $theme;
 
 
 
 
 
 
 
 
89
  }
90
 
91
- // Returns FALSE for Current Theme
92
- function jr_mt_check_all( $type, $rel_url, $ids ) {
93
- // Check Prefix entries first, because we already know there is no specific entry for this URL.
94
- $theme = '';
95
- $match_length = 0;
96
- foreach ( $ids as $key => $array ) {
97
- if ( $array['type'] == 'prefix' ) {
98
- $this_length = strlen( $array['rel_url'] );
99
- if ( $array['rel_url'] == substr( $rel_url, 0, $this_length ) ) {
100
- // Need to find longest match if there are multiple prefix matches.
101
- if ( $this_length > $match_length ) {
102
- $theme = $array['theme'];
103
- $match_length = $this_length;
104
- }
105
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
106
  }
 
107
  }
108
- // See if a Prefix entry was found
109
- if ( $match_length == 0 ) {
110
- if ( $type === FALSE ) {
111
- $theme = FALSE; // Current Theme
112
- } else {
113
- $settings = get_option( 'jr_mt_settings' );
114
- if ( isset( $settings["all_$type"] ) ) {
115
- $theme = $settings["all_$type"];
116
- } else {
117
- $theme = '';
118
- }
119
- if ( empty( $theme ) ) {
120
- $theme = FALSE; // Current Theme
121
  }
122
  }
 
 
123
  }
124
- return $theme;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
125
  }
126
 
127
  ?>
1
  <?php
2
+ /* Exit if .php file accessed directly
3
+ */
4
+ if ( !defined( 'ABSPATH' ) ) {
5
+ exit;
6
+ }
7
 
8
+ /* Disable until old Version Settings conversion done properly,
9
+ typically by displaying the plugin's Settings page in Admin panels.
10
+ */
11
+ if ( ( FALSE === ( $settings = get_option( 'jr_mt_settings' ) ) ) || ( !is_array( $settings ) ) ) {
12
+ return;
13
+ }
14
+ foreach ( array( 'all_pages', 'all_posts', 'site_home', 'current',
15
+ 'url', 'url_prefix', 'url_asterisk',
16
+ 'query', 'remember', 'override',
17
+ 'query_present', 'aliases' ) as $key ) {
18
+ if ( !isset( $settings[ $key ] ) ) {
19
+ return;
20
+ }
21
+ }
22
+ foreach ( array( 'url', 'url_prefix', 'url_asterisk', 'query', 'remember', 'override', 'aliases' ) as $key ) {
23
+ if ( !is_array( $settings[ $key ] ) ) {
24
+ return;
25
+ }
26
+ }
27
+ foreach ( array( 'all_pages', 'all_posts', 'site_home', 'current' ) as $key ) {
28
+ if ( !is_string( $settings[ $key ] ) ) {
29
+ return;
30
+ }
31
+ }
32
+ if ( ( FALSE === ( $internal_settings = get_option( 'jr_mt_internal_settings' ) ) )
33
+ || ( !is_array( $internal_settings ) ) ) {
34
+ return;
35
+ }
36
+
37
+
38
+ /* Select the relevant Theme
39
+ These hooks must be available immediately
40
+ as some Themes check them very early.
41
+ Also must be available in Admin for p2.
42
+ */
43
  add_filter( 'pre_option_stylesheet', 'jr_mt_stylesheet' );
44
  add_filter( 'pre_option_template', 'jr_mt_template' );
45
 
46
+ if ( !is_admin() ) {
47
+ /* Be sure Plugins (non-internal) Settings are present in some shape or form
48
+ for public web site.
49
+ Admin is handled on plugin's Settings page.
50
+ */
51
+ if ( !is_array( get_option( 'jr_mt_settings' ) ) ) {
52
+ update_option( 'jr_mt_settings', jr_mt_default_settings() );
53
+ }
54
+
55
+ /* Hooks below shown in order of execution */
56
+
57
+ /* Only do this if All Posts or All Pages setting is present.
58
+ */
59
+ if ( get_option( 'permalink_structure' ) && jr_mt_all_posts_pages() ) {
60
+ /* 'setup_theme' is the earliest Action that I could find where url_to_postid( $url )
61
+ is valid. get_post() works by then, too.
62
+ */
63
+ add_action( 'setup_theme', 'jr_mt_page_conditional', JR_MT_RUN_FIRST );
64
+ function jr_mt_page_conditional() {
65
+ /* In case any requests for Theme came before this hook,
66
+ make sure that Theme Selection is repeated the next time
67
+ it is needed.
68
+ Because url_to_postid() and possibly get_post() don't work until now.
69
+
70
+ Note: in PHP, you cannot directly unset a global variable,
71
+ hence the cryptic code below.
72
+ */
73
+ unset( $GLOBALS['jr_mt_theme'] );
74
+ DEFINE( 'JR_MT_PAGE_CONDITIONAL', TRUE );
75
+ }
76
+ }
77
+
78
+ add_action( 'wp_loaded', 'jr_mt_wp_loaded', JR_MT_RUN_LAST );
79
+ function jr_mt_wp_loaded() {
80
+ /* Purpose of this hook is to output any required Cookie before it is too late
81
+ (after the <html> or any other HTML is generated).
82
+ There is no performance impact because this effectively pre-caches values
83
+ for use later.
84
+ This timing is also used to enqueue JavaScript related to the Sticky feature.
85
+ */
86
+ global $jr_mt_theme;
87
+ if ( !isset( $jr_mt_theme ) ) {
88
+ $settings = get_option( 'jr_mt_settings' );
89
+ if ( !empty( $settings['remember']['query'] ) ) {
90
+ jr_mt_template();
91
+ }
92
+ }
93
+
94
+ DEFINE( 'JR_MT_TOO_LATE_FOR_COOKIES', TRUE );
95
+ }
96
+ }
97
+
98
  function jr_mt_stylesheet() {
99
  return jr_mt_theme( 'stylesheet' );
100
  }
116
  These three different values for each Theme must be clearly separated, as all three usually
117
  match, but do not have to, e.g. - Child Themes.
118
  */
 
119
  global $jr_mt_theme;
120
  if ( !isset( $jr_mt_theme ) ) {
121
  $jr_mt_theme = array();
122
  }
123
  if ( !isset( $jr_mt_theme[$option] ) ) {
124
  $theme = jr_mt_chosen();
125
+ $jr_mt_all_themes = jr_mt_all_themes();
126
+ /* Check to be sure that Theme is still installed.
127
+ If not:
128
+ return Everywhere theme if set and it exists,
129
+ otherwise, FALSE to indicate WordPress Active Theme.
130
+ */
131
+ if ( ( FALSE !== $theme ) && ( !isset( $jr_mt_all_themes[ $theme ] ) ) ) {
132
+ $settings = get_option( 'jr_mt_settings' );
133
+ $everything = $settings['current'];
134
+ if ( ( '' !== $everything ) && ( isset( $jr_mt_all_themes[ $everything ] ) ) ) {
135
+ $theme = $everything;
136
+ } else {
137
+ $theme = FALSE;
138
+ }
139
+ }
140
+ if ( FALSE === $theme ) {
141
  // Get both at once, to save a repeat of this logic later:
142
  $jr_mt_theme['stylesheet'] = jr_mt_current_theme( 'stylesheet' );
143
  $jr_mt_theme['template'] = jr_mt_current_theme( 'template' );
144
  } else {
145
+ $jr_mt_theme['stylesheet'] = $jr_mt_all_themes[ $theme ]->stylesheet;
146
+ $jr_mt_theme['template'] = $jr_mt_all_themes[ $theme ]->template;
147
+ }
148
+ if ( !is_admin() ) {
149
+ jr_mt_cookie( 'all', 'clean' );
150
  }
151
  }
152
  $theme = $jr_mt_theme[$option];
 
 
 
 
153
  return $theme;
154
  }
155
+
156
+ /**
157
+ * Returns FALSE for Current Theme
158
+ *
159
+ */
160
+ function jr_mt_chosen() {
161
+ $settings = get_option( 'jr_mt_settings' );
162
+
163
+ /* $queries - array of [keyword] => array( value, value, ... )
164
+ in the current URL.
165
+ */
166
+ $queries = jr_mt_query_array();
167
+
168
+ /* KnowHow ThemeForest Paid Theme special processing:
169
+ if s= is present, and 'knowhow' is either the active WordPress Theme
170
+ or is specified in any Settings, then automatically select the KnowHow theme.
171
+ */
172
+ if ( isset( $queries['s'] ) && in_array( 'knowhow', jr_mt_themes_defined(), TRUE ) ) {
173
+ return 'knowhow';
174
+ }
175
 
176
+ /* Non-Admin page, i.e. - Public Site, etc.
177
+
178
+ Begin by checking for any Query keywords specified by the Admin in Settings,
179
+ complicated by the fact that Override entries take precedence.
180
+ */
181
+ if ( !empty( $settings['query'] ) ) {
182
+ if ( !empty( $_SERVER['QUERY_STRING'] ) ) {
183
+ /* Check Override entries
184
+ */
185
+ foreach ( $settings['override']['query'] as $override_keyword => $override_value_array ) {
186
+ if ( isset( $queries[ $override_keyword ] ) ) {
187
+ foreach ( $override_value_array as $override_value_untyped => $bool ) {
188
+ $override_value = ( string ) $override_value_untyped;
189
+ if ( in_array( $override_value, $queries[ $override_keyword ], TRUE ) ) {
190
+ $override_found[] = array( $override_keyword, $override_value );
191
+ }
192
+ }
193
+ }
194
+ }
195
+ if ( !isset( $overrides_found ) ) {
196
+ /* Look for both keyword=value settings and keyword=* settings,
197
+ with keyword=value taking precedence (sorted out later).
198
+ */
199
+ foreach ( $settings['query'] as $query_settings_keyword => $value_array ) {
200
+ if ( isset( $queries[ $query_settings_keyword ] ) ) {
201
+ foreach ( $value_array as $query_settings_value_untyped => $theme ) {
202
+ $query_settings_value = ( string ) $query_settings_value_untyped;
203
+ if ( in_array( $query_settings_value, $queries[ $query_settings_keyword ], TRUE ) ) {
204
+ $query_found[] = array( $query_settings_keyword, $query_settings_value );
205
+ }
206
+ }
207
+ if ( isset( $value_array['*'] ) ) {
208
+ $keyword_found[] = $query_settings_keyword;
209
+ }
210
+ }
211
+ }
212
+ }
213
+ }
214
+ }
215
+
216
+ /* Handle Overrides:
217
+ First, for Override keyword=value query in URL.
218
+ Second, for previous Override detected by PHP cookie.
219
+ */
220
+ if ( isset( $override_found ) ) {
221
+ /* If sticky, create JavaScript Sticky Cookie,
222
+ and PHP Sticky Cookie.
223
+ No matter what:
224
+ return Theme from the first Override found.
225
+ */
226
+ $keyword = $override_found[0][0];
227
+ $value = $override_found[0][1];
228
+ if ( isset( $settings['remember']['query'][ $keyword ][ $value ] ) ) {
229
+ jr_mt_js_sticky_query( $keyword, $value );
230
+ jr_mt_cookie( 'php', 'put', "$keyword=$value" );
231
  }
232
+ return $settings['query'][ $keyword ][ $value ];
233
  } else {
234
+ /* Is there a previous Override Query for this Site Visitor?
235
+ If so, use it, but only if it is still valid.
236
+ */
237
+ if ( FALSE !== ( $cookie = jr_mt_cookie( 'php', 'get' ) ) ) {
238
+ list( $keyword, $value ) = explode( '=', $cookie );
239
+ if ( isset( $settings['override']['query'][ $keyword ][ $value ] ) ) {
240
+ /* If sticky, create JavaScript Sticky Cookie,
241
+ and renew PHP Sticky Cookie.
242
+ No matter what:
243
+ Return Theme
244
+ */
245
+ if ( isset( $settings['remember']['query'][ $keyword ][ $value ] ) ) {
246
+ jr_mt_js_sticky_query( $keyword, $value );
247
+ jr_mt_cookie( 'php', 'put', "$keyword=$value" );
248
+ }
249
+ return $settings['query'][ $keyword ][ $value ];
250
+ }
251
+ }
252
+ }
253
+
254
+ /* Handle Non-Overrides:
255
+ keyword=value query in URL with matching setting entry.
256
+ */
257
+ if ( isset( $query_found ) ) {
258
+ $query_keyword_found = $query_found[0][0];
259
+ $query_value_found = $query_found[0][1];
260
+ /* Probably makes sense to give preference to the Sticky ones
261
+ */
262
+ foreach ( $query_found as $query_kwval_array ) {
263
+ if ( isset( $settings['remember']['query'][ $query_kwval_array[0] ][ $query_kwval_array[1] ] ) ) {
264
+ $query_keyword_found = $query_kwval_array[0];
265
+ $query_value_found = $query_kwval_array[1];
266
+ /* Create JavaScript Sticky Cookie,
267
+ and PHP Sticky Cookie.
268
+ */
269
+ jr_mt_js_sticky_query( $query_keyword_found, $query_value_found );
270
+ jr_mt_cookie( 'php', 'put', "$query_keyword_found=$query_value_found" );
271
+ break;
272
  }
273
  }
274
+ /* Return Theme
275
+ */
276
+ return $settings['query'][ $query_keyword_found ][ $query_value_found ];
277
+ }
278
+
279
+ /* Handle Keyword wildcards:
280
+ keyword=* setting entry that matches keyword in URL query.
281
+ */
282
+ if ( isset( $keyword_found ) ) {
283
+ return $settings['query'][ $keyword_found[0] ]['*'];
284
+ }
285
+
286
+ /* Now look at URL entries: $settings['url'] and ['url_prefix']
287
+
288
+ Version 6.0 Logic Design to maximize performance on high traffic sites without Caching:
289
+ For current URL, determine Site Alias in use
290
+ - Best Match - from an array of matching Site Aliases, determine "Best", some measure of Longest
291
+ Prep current URL for matching
292
+ Check for match in "URL" plugin entries that have been pre-prepped with this Site Alias
293
+ Check for match in "URL Prefix" plugin entries that have been pre-prepped with this Site Alias
294
+ Check for match in "URL Prefix with Asterisk" plugin entries that have been pre-prepped with this Site Alias
295
+ */
296
+
297
+ if ( 0 === ( $port = jr_mt_non_default_port( $_SERVER, 'SERVER_PORT' ) ) ) {
298
+ $url_port = '';
299
+ } else {
300
+ $url_port = ':' . $port;
301
+ }
302
+ $prep_url = jr_mt_prep_url( $current_url = parse_url( JR_MT_HOME_URL, PHP_URL_SCHEME )
303
+ . '://'
304
+ . $_SERVER['SERVER_NAME']
305
+ . $url_port
306
+ . $_SERVER['REQUEST_URI'] );
307
+ $match = array();
308
+ foreach ( $settings['aliases'] as $key => $alias_array ) {
309
+ if ( jr_mt_same_prefix_url( $alias_array['prep'], $prep_url ) ) {
310
+ $match[] = $key;
311
+ }
312
+ }
313
+ if ( empty( $match ) ) {
314
+ /* Maybe not the best thing to do,
315
+ but if Site Alias is not defined,
316
+ always use Current Theme.
317
+ */
318
+ return FALSE;
319
+ }
320
+ $site_alias_key = jr_mt_best_match_alias( $settings['aliases'], $match );
321
+ foreach ( $settings['url'] as $settings_array ) {
322
+ if ( jr_mt_same_url( $settings_array['prep'][ $site_alias_key ], $prep_url ) ) {
323
+ return $settings_array['theme'];
324
+ }
325
+ }
326
+ foreach ( $settings['url_prefix'] as $settings_array ) {
327
+ if ( jr_mt_same_prefix_url( $settings_array['prep'][ $site_alias_key ], $prep_url ) ) {
328
+ return $settings_array['theme'];
329
+ }
330
+ }
331
+ foreach ( $settings['url_asterisk'] as $settings_array ) {
332
+ if ( jr_mt_same_prefix_url_asterisk( $settings_array['prep'][ $site_alias_key ], $prep_url ) ) {
333
+ return $settings_array['theme'];
334
+ }
335
+ }
336
+
337
+ /* Theme to use for All /wp-admin/admin-ajax.php usage.
338
+ Selected near the end to allow Queries to take precedence.
339
+ */
340
+ if ( !empty( $settings['ajax_all'] )
341
+ && ( FALSE !== strpos( $_SERVER['REQUEST_URI'], 'admin-ajax.php' ) ) ) {
342
+ return $settings['ajax_all'];
343
+ }
344
+
345
+ /* Must check for Home near the end as queries override
346
+
347
+ Home is determined in an odd way:
348
+ (1) Remove all Queries
349
+ (2) Match against Site Address (URL) specified in Admin General Settings
350
+ (3) Check if any non-Permalink keywords are present, such as p= or page_id=
351
+ and cause a non-match if present
352
+ */
353
+ if ( '' !== $settings['site_home'] ) {
354
+ /* Check for Home Page,
355
+ with or without Query.
356
+ */
357
+ $prep_url_no_query = $prep_url;
358
+ $prep_url_no_query['query'] = array();
359
+ if ( jr_mt_same_url( JR_MT_HOME_URL, $prep_url_no_query ) ) {
360
+ $home = TRUE;
361
+ $internal_settings = get_option( 'jr_mt_internal_settings' );
362
+ if ( ( isset( $internal_settings['query_vars'] ) )
363
+ && ( is_array( $internal_settings['query_vars'] ) ) ) {
364
+ foreach ( $prep_url['query'] as $keyword => $value ) {
365
+ /* Check for any non-Permalink Query Keyword
366
+ */
367
+ if ( in_array( $keyword, $internal_settings['query_vars'], TRUE ) ) {
368
+ $home = FALSE;
369
+ break;
370
+ }
371
+ }
372
+ }
373
+ if ( $home ) {
374
+ return $settings['site_home'];
375
  } else {
376
+ /* Check for Settings specifying the current Page, Post or Attachment
377
+ specified with kw=val Query default Permalinks.
378
+ */
379
+ foreach ( $settings['url'] as $settings_array ) {
380
+ if ( isset( $settings_array['id_kw'] )
381
+ && ( isset( $prep_url['query'][ $settings_array['id_kw'] ] ) )
382
+ && ( $prep_url['query'][ $settings_array['id_kw'] ] === $settings_array['id'] )
383
+ ) {
384
+ return $settings_array['theme'];
385
+ }
386
+ }
387
+ }
388
+ }
389
+ }
390
+ /* All Pages and All Posts settings are checked second to last,
391
+ just before Everything Else.
392
+
393
+ url_to_postid() only works after JR_MT_PAGE_CONDITIONAL is set.
394
+ But alternate means can be used with default Permalinks.
395
+
396
+ First, see if any All Pages or All Posts setting exists.
397
+ */
398
+ if ( jr_mt_all_posts_pages() ) {
399
+ if ( defined( 'JR_MT_PAGE_CONDITIONAL' ) ) {
400
+ if ( 0 !== ( $id = url_to_postid( $current_url ) ) ) {
401
+ if ( NULL !== ( $post = get_post( $id ) ) ) {
402
+ $type = $post->post_type;
403
+ if ( 'post' === $type ) {
404
+ if ( '' !== $settings['all_posts'] ) {
405
+ return $settings['all_posts'];
406
+ }
407
+ } else {
408
+ if ( 'page' === $type ) {
409
+ if ( '' !== $settings['all_pages'] ) {
410
+ return $settings['all_pages'];
411
+ }
412
+ }
413
+ }
414
+ }
415
  }
416
  } else {
417
+ $permalink = get_option( 'permalink_structure' );
418
+ if ( empty( $permalink ) ) {
419
+ if ( '' !== $settings['all_posts'] ) {
420
+ if ( isset( $queries['p'] ) ) {
421
+ return $settings['all_posts'];
422
+ }
423
+ }
424
+
425
+ if ( '' !== $settings['all_pages'] ) {
426
+ if ( isset( $queries['page_id'] ) ) {
427
+ return $settings['all_pages'];
428
+ }
429
+ }
430
  }
431
  }
432
  }
433
+ /* This is the Theme for Everything Advanced Setting.
434
+ A Setting of Blank uses WordPress Current Theme value,
435
+ i.e. - the Setting is not set.
436
+ */
437
+ if ( '' === $settings['current'] ) {
438
+ return FALSE;
439
+ } else {
440
+ return $settings['current'];
441
+ }
442
  }
443
 
444
+ /** Cookie to JavaScript with Sticky Query and related info.
445
+
446
+ Replace Existing or Create New (if no existing) Cookie
447
+ to remember what Sticky Keyword=Value to use on this Browser on this Visitor Computer.
448
+ Cookie is an encoding of this array:
449
+ - keyword=value query to append to URL
450
+ - FALSE if Setting "Append if no question mark ("?") found in URL", or
451
+ TRUE if Setting "Append if no Override keyword=value found in URL"
452
+ - an array of all sticky or override queries (empty array if FALSE)
453
+
454
+ Version 6.0 - this code has not been upgraded to support Site Aliases!
455
+ */
456
+ function jr_mt_js_sticky_query( $keyword, $value ) {
457
+ add_action( 'wp_enqueue_scripts', 'jr_mt_wp_enqueue_scripts' );
458
+ function jr_mt_wp_enqueue_scripts() {
459
+ global $jr_mt_plugin_data;
460
+ wp_enqueue_script( 'jr_mt_sticky', plugins_url() . '/' . dirname( jr_mt_plugin_basename() ) . '/js/sticky.js', array(), $jr_mt_plugin_data['Version'] );
461
+ /* JavaScript needs some values passed in HTML,
462
+ so add that hook here, too.
463
+ */
464
+ add_action( 'wp_footer', 'jr_mt_wp_footer' );
465
+ }
466
+ function jr_mt_wp_footer() {
467
+ echo '<div style="display: none;"><div id="jr-mt-home-url" title="'
468
+ . jr_mt_prep_comp_url( JR_MT_HOME_URL )
469
+ . '"></div><div id="jr-mt-site-admin" title="'
470
+ . jr_mt_prep_comp_url( admin_url() )
471
+ . '"></div></div>';
472
+ }
473
+ /** Prepare URL for JavaScript compares
474
+
475
+ Remove http[s]//: from beginning
476
+ Convert rest of URL to lower-case
477
+ Remove www. from beginning, if present
478
+ Convert any backslashes to forward slashes
479
+ Remove any trailing slash(es).
480
+ */
481
+ function jr_mt_prep_comp_url( $url ) {
482
+ $comp_url = jr_mt_strtolower( jr_mt_substr( $url, 3 + strpos( $url, '://' ) ) );
483
+ if ( 'www.' === jr_mt_substr( $comp_url, 0, 4 ) ) {
484
+ $comp_url = jr_mt_substr( $comp_url, 4 );
485
  }
486
+ return rtrim( str_replace( '\\', '/', $comp_url ), '/' );
487
  }
488
+
489
+ $settings = get_option( 'jr_mt_settings' );
490
+
491
+ if ( $settings['query_present'] ) {
492
+ foreach ( $settings['override']['query'] as $override_keyword => $override_value_array ) {
493
+ foreach ( $override_value_array as $override_value => $theme ) {
494
+ $override[] = "$override_keyword=$override_value";
 
 
 
 
 
 
495
  }
496
  }
497
+ } else {
498
+ $override = array();
499
  }
500
+
501
+ jr_mt_cookie( 'js', 'put', strtr( rawurlencode( json_encode(
502
+ array( "$keyword=$value", $settings['query_present'], $override ) ) ),
503
+ array( '%21' => '!', '%2A' => '*', '%27' => "'", '%28' => '(', '%29' => ')' ) )
504
+ );
505
+ }
506
+
507
+ /* All Cookie Handling occurs here.
508
+ $action - 'get', 'put', 'del'
509
+ */
510
+ function jr_mt_cookie( $lang, $action, $cookie_value = '' ) {
511
+ switch ( $lang ) {
512
+ case 'js':
513
+ $cookie_name = 'jr-mt-remember-query';
514
+ $raw = TRUE;
515
+ $expiry = '+36 hours';
516
+ $function = 'setrawcookie';
517
+ break;
518
+ case 'php':
519
+ $cookie_name = 'jr_mt_php_override_query';
520
+ $raw = FALSE;
521
+ $expiry = '+1 year';
522
+ $function = 'setcookie';
523
+ break;
524
+ }
525
+ if ( 'get' === $action ) {
526
+ if ( isset( $_COOKIE[ $cookie_name ] ) ) {
527
+ return $_COOKIE[ $cookie_name ];
528
+ } else {
529
+ return FALSE;
530
+ }
531
+ } else {
532
+ global $jr_mt_cookie_track;
533
+ if ( defined( 'JR_MT_TOO_LATE_FOR_COOKIES' ) ) {
534
+ return FALSE;
535
+ }
536
+ /* Determine Path off Domain to WordPress Address, not Site Address, for Cookie Path value.
537
+ Using home_url().
538
+ */
539
+ $cookie_path = parse_url( JR_MT_HOME_URL, PHP_URL_PATH ) . '/';
540
+ switch ( $action ) {
541
+ case 'put':
542
+ if ( empty( $cookie_value ) ) {
543
+ return FALSE;
544
+ } else {
545
+ return ( $jr_mt_cookie_track[ $lang ] = $function( $cookie_name, $cookie_value, strtotime( $expiry ), $cookie_path, $_SERVER['SERVER_NAME'] ) );
546
+ }
547
+ break;
548
+ case 'del':
549
+ /* Don't clutter up output to browser with a Cookie Delete request if a Cookie does not exist.
550
+ */
551
+ if ( isset( $_COOKIE[ $cookie_name ] ) ) {
552
+ return ( $jr_mt_cookie_track[ $lang ] = setrawcookie( $cookie_name, '', strtotime( '-2 days' ), $cookie_path, $_SERVER['SERVER_NAME'] ) );
553
+ }
554
+ break;
555
+ case 'clean':
556
+ if ( 'all' === $lang ) {
557
+ $clean_langs = array( 'php', 'js' );
558
+ } else {
559
+ $clean_langs = array( $lang );
560
+ }
561
+ foreach ( $clean_langs as $clean_lang ) {
562
+ if ( !isset( $jr_mt_cookie_track[ $clean_lang ] ) ) {
563
+ jr_mt_cookie( $clean_lang, 'del' );
564
+ }
565
+ }
566
+ break;
567
+ }
568
+ }
569
+ }
570
+
571
+ /** Will the url_to_postid() function be required?
572
+ *
573
+ * Only if:
574
+ * - Pretty Permalinks are being used, AND
575
+ * - ( All Posts setting is set, OR
576
+ * - All Pages setting is set )
577
+ * @return bool if add_action is required
578
+ */
579
+ function jr_mt_all_posts_pages() {
580
+ $settings = get_option( 'jr_mt_settings' );
581
+ return ( $settings['all_posts'] || $settings['all_pages'] );
582
  }
583
 
584
  ?>
includes/upgradev5.php ADDED
@@ -0,0 +1,126 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /* Exit if .php file accessed directly
4
+ */
5
+ if ( !defined( 'ABSPATH' ) ) {
6
+ exit;
7
+ }
8
+
9
+ /**
10
+ * Convert pre-Version 5 ['ids'] Settings to new Version 5 format.
11
+ *
12
+ * Mainly, it involves converting Post ID to URL.
13
+ * 'setup_theme' is the earliest Action where
14
+ * all functions in jr_mt_convert_ids() work properly.
15
+ *
16
+ */
17
+ function jr_mt_convert_ids( $settings ) {
18
+ if ( is_array( $settings['ids'] ) ) {
19
+ foreach ( $settings['ids'] as $key => $ids_array ) {
20
+ /* Be sure that Theme has not been deleted.
21
+ */
22
+ $jr_mt_all_themes = jr_mt_all_themes();
23
+ if ( isset( $jr_mt_all_themes[ $ids_array['theme'] ] ) ) {
24
+ /* $key:
25
+ '' - Home entry
26
+ */
27
+ if ( '' === $key ) {
28
+ if ( '' === $settings['site_home'] ) {
29
+ $settings['site_home'] = $ids_array['theme'];
30
+ }
31
+ } else {
32
+ if ( isset( $ids_array['type'] ) ) {
33
+ switch ( $ids_array['type'] ) {
34
+ case 'admin':
35
+ /* Ignore as Admin pages are ignored
36
+ */
37
+ break;
38
+ case 'prefix':
39
+ /* URL Prefix
40
+ */
41
+ $url = JR_MT_HOME_URL . "/$key";
42
+ $settings['url_prefix'][] = array(
43
+ 'url' => $url,
44
+ 'prep' => jr_mt_prep_url( $url ),
45
+ 'theme' => $ids_array['theme']
46
+ );
47
+ break;
48
+ case '*':
49
+ /* URL Prefix with Asterisk
50
+ */
51
+ $url = JR_MT_HOME_URL . "/$key";
52
+ $settings['url_asterisk'][] = array(
53
+ 'url' => $url,
54
+ 'prep' => jr_mt_prep_url( $url ),
55
+ 'theme' => $ids_array['theme']
56
+ );
57
+ break;
58
+ case 'cat':
59
+ if ( is_wp_error( get_the_category_by_ID( $key ) ) ) {
60
+ /* Ignore non-existent Categories.
61
+ They were likely deleted.
62
+ */
63
+ jr_mt_messages( 'Setting deleted for non-existent Category with ID=' . $key );
64
+ } else {
65
+ $url = get_category_link( $key );
66
+ $settings['url'][] = array(
67
+ 'url' => $url,
68
+ 'prep' => jr_mt_prep_url( $url ),
69
+ 'theme' => $ids_array['theme']
70
+ );
71
+ }
72
+ break;
73
+ case 'archive':
74
+ /* From ?m=yyyymm query originally
75
+ */
76
+ $yyyymm = $ids_array['id'];
77
+ $year = intval( $yyyymm / 100 );
78
+ $month = $yyyymm % 100;
79
+ $url = get_month_link( $year, $month );
80
+ $settings['url'][] = array(
81
+ 'url' => $url,
82
+ 'prep' => jr_mt_prep_url( $url ),
83
+ 'theme' => $ids_array['theme']
84
+ );
85
+ break;
86
+ default:
87
+ if ( FALSE === $ids_array['id'] ) {
88
+ /* Exact URL
89
+ */
90
+ $url = JR_MT_HOME_URL . "/$key";
91
+ $settings['url'][] = array(
92
+ 'url' => $url,
93
+ 'prep' => jr_mt_prep_url( $url ),
94
+ 'theme' => $ids_array['theme']
95
+ );
96
+ } else {
97
+ /* Some Post type
98
+
99
+ get_permalink() can be used as early as Action Hook 'setup_theme',
100
+ but not in 'plugins_loaded' (Fatal Error).
101
+ */
102
+ if ( FALSE === ( $url = get_permalink( $key ) ) ) {
103
+ /* Ignore any non-existent IDs, typically deleted.
104
+ */
105
+ jr_mt_messages( 'Setting deleted for non-existent Post/Page/Attachment with ID=' . $key );
106
+ } else {
107
+ $settings['url'][] = array(
108
+ 'url' => $url,
109
+ 'prep' => jr_mt_prep_url( $url ),
110
+ 'theme' => $ids_array['theme']
111
+ );
112
+ }
113
+ }
114
+ }
115
+ }
116
+ }
117
+ }
118
+ }
119
+ }
120
+ /* Maybe later:
121
+ unset( $settings['ids'] );
122
+ */
123
+ return $settings;
124
+ }
125
+
126
+ ?>
includes/upgradev6.php ADDED
@@ -0,0 +1,71 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ /* Exit if .php file accessed directly
4
+ */
5
+ if ( !defined( 'ABSPATH' ) ) {
6
+ exit;
7
+ }
8
+
9
+ /* Must be able to determine Page ID (Action setup_theme is the earliest)
10
+ */
11
+ function jr_mt_convert_url_arrays( $settings ) {
12
+ global $jr_mt_url_types;
13
+ foreach ( $jr_mt_url_types as $setting_key ) {
14
+ if ( isset( $settings[ $setting_key ] )
15
+ && is_array( $settings[ $setting_key ] ) ) {
16
+ foreach ( $settings[ $setting_key ] as $url_key => $url_array ) {
17
+ $url = $url_array['url'];
18
+ if ( jr_mt_same_prefix_url( JR_MT_HOME_URL, $url ) ) {
19
+ $new_url_array['url'] = $url_array['url'];
20
+ $new_url_array['theme'] = $url_array['theme'];
21
+ $rel_url = jr_mt_relative_url( $url, JR_MT_HOME_URL );
22
+ $new_url_array['rel'] = $rel_url;
23
+ /* Create the URL Prep array for each of the current Site Aliases,
24
+ including the Current Site URL
25
+ */
26
+ $new_url_array['prep'] = array();
27
+ foreach ( $settings['aliases'] as $index => $alias ) {
28
+ $new_url_array['prep'][] = jr_mt_prep_url( $alias['url'] . '/' . $rel_url );
29
+ }
30
+ /* Only for URL type Setting, not Prefix types.
31
+ */
32
+ if ( 'url' === $setting_key ) {
33
+ /* Try and figure out ID and WordPress Query Keyword for Type, if possible and relevant
34
+ */
35
+ if ( ( 0 === ( $id = url_to_postid( $url ) ) ) &&
36
+ ( version_compare( get_bloginfo( 'version' ), '4', '>=' ) ) ) {
37
+ $id = attachment_url_to_postid( $url );
38
+ }
39
+ if ( !empty( $id ) ) {
40
+ $new_url_array['id'] = ( string ) $id;
41
+ if ( NULL !== ( $post = get_post( $id ) ) ) {
42
+ switch ( $post->post_type ) {
43
+ case 'post':
44
+ $new_url_array['id_kw'] = 'p';
45
+ break;
46
+ case 'page':
47
+ $new_url_array['id_kw'] = 'page_id';
48
+ break;
49
+ case 'attachment':
50
+ $new_url_array['id_kw'] = 'attachment_id';
51
+ break;
52
+ }
53
+ }
54
+ }
55
+ }
56
+ $settings[ $setting_key ][ $url_key ] = $new_url_array;
57
+ } else {
58
+ /* Error:
59
+ Cannot convert, as URL is from a different Site Home URL,
60
+ so have to delete this URL entry.
61
+ */
62
+ unset( $settings[ $setting_key ][ $url_key ] );
63
+ jr_mt_messages( 'Setting deleted during Conversion to Version 6 format because Site URL has changed' );
64
+ }
65
+ }
66
+ }
67
+ }
68
+ return $settings;
69
+ }
70
+
71
+ ?>
index.html ADDED
File without changes
jonradio-multiple-themes.php CHANGED
@@ -2,14 +2,14 @@
2
  /*
3
  Plugin Name: jonradio Multiple Themes
4
  Plugin URI: http://zatzlabs.com/plugins/
5
- Description: Select different Themes for one or more, or all WordPress Pages, Posts or other non-Admin pages. Or Site Home.
6
- Version: 4.0.2
7
  Author: David Gewirtz
8
  Author URI: http://zatzlabs.com/plugins/
9
  License: GPLv2
10
  */
11
 
12
- /* Copyright 2013 jonradio (email : info@zatz.com)
13
 
14
  This program is free software; you can redistribute it and/or modify
15
  it under the terms of the GNU General Public License as published by
@@ -26,145 +26,165 @@ License: GPLv2
26
  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
27
  */
28
 
29
- global $jr_mt_plugin_folder;
30
- $jr_mt_plugin_folder = basename( dirname( __FILE__ ) );
31
-
32
- function jr_mt_plugin_folder() {
33
- global $jr_mt_plugin_folder;
34
- return $jr_mt_plugin_folder;
35
- }
36
-
37
- global $jr_mt_path;
38
- $jr_mt_path = plugin_dir_path( __FILE__ );
39
- function jr_mt_path() {
40
- global $jr_mt_path;
41
- return $jr_mt_path;
42
  }
43
 
44
- global $jr_mt_plugin_basename;
45
- $jr_mt_plugin_basename = plugin_basename( __FILE__ );
46
 
47
- if ( !function_exists( 'get_plugin_data' ) ) {
48
- require_once( ABSPATH . 'wp-admin/includes/plugin.php' );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
49
  }
50
 
51
- global $jr_mt_plugin_data;
52
- $jr_mt_plugin_data = get_plugin_data( __FILE__ );
53
-
54
- global $jr_mt_options_cache;
55
- $all_options = wp_load_alloptions();
56
- $jr_mt_options_cache['stylesheet'] = $all_options['stylesheet'];
57
- $jr_mt_options_cache['template'] = $all_options['template'];
 
 
58
 
59
- register_activation_hook( __FILE__, 'jr_mt_activate' );
60
- register_deactivation_hook( __FILE__, 'jr_mt_deactivate' );
61
-
62
- function jr_mt_activate( $network_wide ) {
63
- if ( $network_wide ) {
64
- global $wpdb, $site_id;
65
- $blogs = $wpdb->get_results( "SELECT blog_id FROM {$wpdb->blogs} WHERE site_id = $site_id" );
66
- foreach ( $blogs as $blog_obj ) {
67
- if ( switch_to_blog( $blog_obj->blog_id ) ) {
68
- // We know the Site actually exists
69
- jr_mt_activate1();
70
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
71
  }
72
- restore_current_blog();
73
- } else {
74
- jr_mt_activate1();
75
  }
76
- }
77
-
78
- function jr_mt_activate1() {
79
- $settings = array(
80
- 'all_pages' => '',
81
- 'all_posts' => '',
82
- 'site_home' => '',
83
- 'ids' => array()
84
- );
85
- // Nothing happens if Settings already exist
86
- add_option( 'jr_mt_settings', $settings );
87
 
88
- global $jr_mt_plugin_data;
89
- $internal_settings = array(
90
- 'version' => $jr_mt_plugin_data['Version']
91
- ); // Only records you version when plugin installed, not current version
92
- add_option( 'jr_mt_internal_settings', $internal_settings ); // Nothing happens if Settings already exist
93
- }
94
-
95
- add_action( 'wpmu_new_blog', 'jr_mt_new_site', 10, 6 );
96
-
97
- function jr_mt_new_site( $blog_id, $user_id, $domain, $path, $site_id, $meta ) {
98
- if ( is_plugin_active_for_network( plugin_basename( __FILE__ ) ) ) {
99
- switch_to_blog( $blog_id );
100
- jr_mt_activate1();
101
- restore_current_blog();
102
- }
103
- }
104
-
105
- function jr_mt_deactivate() {
106
- // Nothing (yet)
107
- }
108
-
109
- jr_mt_version_check();
110
-
111
- function jr_mt_version_check() {
112
- // Check for Plugin Version update (Deactivate and Activate Hooks not fired)
113
- $internal_settings = get_option( 'jr_mt_internal_settings' );
114
- if ( $internal_settings ) { // Just in case Activation has not occurred yet
115
- global $jr_mt_plugin_data;
116
- if ( version_compare( $internal_settings['version'], $jr_mt_plugin_data['Version'], '<' ) ) {
117
- $settings = get_option( 'jr_mt_settings' );
118
- if ( isset( $settings['ids'] ) ) {
119
- $ids = $settings['ids'];
120
- } else {
121
- $ids = array();
122
- }
123
- if ( version_compare( $internal_settings['version'], '2.1', '<' ) ) {
124
- unset( $settings['all_admin'] );
125
- // Check for Site Home entry, remove it and set Site Home field
126
- // And remove all Admin entries (no longer supported)
127
- if ( isset( $ids[''] ) ) {
128
- $settings['site_home'] = $ids['']['theme'];
129
- unset( $ids[''] );
130
- } else {
131
- $settings['site_home'] = '';
132
- }
133
- foreach ( $ids as $key => $arr ) {
134
- if ( $arr['type'] == 'admin' ) {
135
- unset( $ids[$key] );
136
- }
137
- }
138
- }
139
- if ( version_compare( $internal_settings['version'], '3.0', '<' ) ) {
140
- foreach ( $ids as $key => $arr ) {
141
- if ( strcasecmp( 'http', substr( $arr['rel_url'], 0, 4 ) ) == 0 ) {
142
- unset( $ids[$key] );
143
- }
144
- }
145
- }
146
- $settings['ids'] = $ids;
147
- update_option( 'jr_mt_settings', $settings );
148
- $internal_settings['version'] = $jr_mt_plugin_data['Version'];
149
- update_option( 'jr_mt_internal_settings', $internal_settings );
150
- }
151
  }
152
  }
153
 
154
- require_once( jr_mt_path() . 'includes/functions.php' );
155
- require_once( jr_mt_path() . 'includes/select-theme.php' );
156
-
157
- if ( is_admin() ) {
158
- // Admin panel
159
- require_once( jr_mt_path() . 'includes/admin.php' );
160
- }
161
-
162
- /*
163
- Research Notes:
164
- The first time one of these Filter Hooks fires, pre_option_stylesheet and pre_option_template, only the following functions can be used to help determine "where" you are in the site:
165
- - is_admin()
166
- - is_user_logged_in()
167
- - get_option("page_on_front") - ID of home page; zero if Reading Settings NOT set to a Static Page of a WordPress Page
168
- */
169
-
170
  ?>
2
  /*
3
  Plugin Name: jonradio Multiple Themes
4
  Plugin URI: http://zatzlabs.com/plugins/
5
+ Description: Select different Themes for one or more WordPress Pages, Posts or other non-Admin pages. Or Site Home.
6
+ Version: 7.1
7
  Author: David Gewirtz
8
  Author URI: http://zatzlabs.com/plugins/
9
  License: GPLv2
10
  */
11
 
12
+ /* Copyright 2015 jonradio (email : info@zatz.com)
13
 
14
  This program is free software; you can redistribute it and/or modify
15
  it under the terms of the GNU General Public License as published by
26
  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
27
  */
28
 
29
+ /* Exit if .php file accessed directly
30
+ */
31
+ if ( !defined( 'ABSPATH' ) ) {
32
+ exit;
 
 
 
 
 
 
 
 
 
33
  }
34
 
35
+ DEFINE( 'JR_MT_HOME_URL', home_url() );
36
+ DEFINE( 'JR_MT_FILE', __FILE__ );
37
 
38
+ /* For Hooks, when it needs to run first or last.
39
+ */
40
+ DEFINE( 'JR_MT_RUN_FIRST', 1 );
41
+ DEFINE( 'JR_MT_RUN_SECOND', JR_MT_RUN_FIRST + 1 );
42
+ DEFINE( 'JR_MT_RUN_LAST', 999 );
43
+
44
+ DEFINE( 'JR_MT_WP_GET_THEMES_ACTION', 'plugins_loaded' );
45
+
46
+ global $jr_mt_url_types;
47
+ $jr_mt_url_types = array( 'url', 'url_prefix', 'url_asterisk' );
48
+
49
+ function jr_mt_default_settings() {
50
+ return array(
51
+ /* Settings structure:
52
+ code - get_option( 'jr_mt_settings' )
53
+ ['all_pages'] => zero length string or folder in Themes directory containing theme to use for All Pages
54
+ ['all_posts'] => zero length string or folder in Themes directory containing theme to use for All Posts
55
+ ['site_home'] => zero length string or folder in Themes directory containing theme to use for Home Page
56
+ ['current'] => zero length string or folder in Themes directory containing theme to override WordPress Current Theme
57
+ ['query']
58
+ [keyword]
59
+ [value] or ['*'] => folder in Themes directory containing theme to use
60
+ ['remember']
61
+ ['query']
62
+ [keyword]
63
+ [value] => TRUE
64
+ ['override']
65
+ ['query']
66
+ [keyword]
67
+ [value] => TRUE
68
+ ['query_present'] => TRUE or FALSE
69
+
70
+ Added in Version 5.0:
71
+ ['url'], ['url_prefix'] and ['url_asterisk'] - array with each entry:
72
+ ['url'] => URL
73
+ ['prep'][] => array of URL arrays created by jr_mt_prep_url(), with array index matching the array index of ['aliases']
74
+ ['rel_url'] => Relative URL based on Site Address (URL) that admin entered the URL
75
+ ['id'] => Post ID (Page, Post or Attachment), if known and if relevant
76
+ ['id_kw'] => 'page_id', 'p' or 'attachment_id'
77
+ ['theme'] => folder in Themes directory containing theme to use
78
+
79
+ Added in Version 6.0:
80
+ ['aliases'][] - array of Alias URLs that could replace 'home' in URL of this site,
81
+ with each entry:
82
+ ['url'] => URL
83
+ ['prep'] => URL array created by jr_mt_prep_url()
84
+ ['home'] => TRUE if this is Site Address (URL) field value from WordPress General Settings,
85
+ which is stored here to determine when the WordPress General Setting is changed
86
+
87
+ Added in Version 7.1:
88
+ ['ajax_all'] => zero length string or folder in Themes directory containing theme to use for /wp-admin/admin-ajax.php
89
+
90
+ Prior to Version 5.0:
91
+ ['ids']
92
+ [id] - zero length string or WordPress ID of Page, Post, etc.
93
+ ['type'] => 'page' or 'post' or 'admin' or 'cat' or 'archive' or 'prefix' or other
94
+ ['theme'] => folder in Themes directory containing theme to use
95
+ ['id'] => FALSE or WordPress ID of Page, Post, etc.
96
+ ['page_url'] => relative URL WordPress page, post, admin, etc. or FALSE
97
+ ['rel_url'] => URL relative to WordPress home
98
+ ['url'] => original full URL, from Settings page entry by user
99
+ */
100
+ 'aliases' => jr_mt_init_aliases(),
101
+ 'all_pages' => '',
102
+ 'all_posts' => '',
103
+ 'site_home' => '',
104
+ 'current' => '',
105
+ 'ajax_all' => '',
106
+ 'query' => array(),
107
+ 'remember' => array( 'query' => array() ),
108
+ 'override' => array( 'query' => array() ),
109
+ 'query_present' => FALSE,
110
+ 'url' => array(),
111
+ 'url_prefix' => array(),
112
+ 'url_asterisk' => array()
113
+ );
114
  }
115
 
116
+ /* Catch old unsupported version of WordPress before any damage can be done.
117
+ */
118
+ if ( version_compare( get_bloginfo( 'version' ), '3.4', '<' ) ) {
119
+ require_once( plugin_dir_path( JR_MT_FILE ) . 'includes/old-wp.php' );
120
+ } else {
121
+ /* Use $plugin_data['Name'] for the array of incompatible plugins
122
+ */
123
+ global $jr_mt_incompat_plugins;
124
+ $jr_mt_incompat_plugins = array( 'Theme Test Drive' ); // removed for V5: 'BuddyPress', 'Polylang'
125
 
126
+ require_once( plugin_dir_path( JR_MT_FILE ) . 'includes/functions.php' );
127
+
128
+ if ( is_admin() ) {
129
+ /* Add Link to the plugin's entry on the Admin "Plugins" Page, for easy access
130
+
131
+ Placed here to avoid the confusion of not displaying it during a Version conversion of Settings
132
+ */
133
+ add_filter( 'plugin_action_links_' . jr_mt_plugin_basename(), 'jr_mt_plugin_action_links', 10, 1 );
134
+
135
+ /**
136
+ * Creates Settings entry right on the Plugins Page entry.
137
+ *
138
+ * Helps the user understand where to go immediately upon Activation of the Plugin
139
+ * by creating entries on the Plugins page, right beside Deactivate and Edit.
140
+ *
141
+ * @param array $links Existing links for our Plugin, supplied by WordPress
142
+ * @param string $file Name of Plugin currently being processed
143
+ * @return string $links Updated set of links for our Plugin
144
+ */
145
+ function jr_mt_plugin_action_links( $links ) {
146
+ /* The "page=" query string value must be equal to the slug
147
+ of the Settings admin page.
148
+ */
149
+ array_unshift( $links, '<a href="' . get_bloginfo('wpurl') . '/wp-admin/admin.php?page=jr_mt_settings' . '">Settings</a>' );
150
+ return $links;
151
+ }
152
+
153
+ // Admin Page
154
+
155
+ add_action( 'admin_menu', 'jr_mt_admin_hook' );
156
+ // Runs just before admin_init (in admin.php file)
157
+
158
+ /**
159
+ * Add Admin Menu item for plugin
160
+ *
161
+ * Plugin needs its own Page in the Settings section of the Admin menu.
162
+ *
163
+ */
164
+ function jr_mt_admin_hook() {
165
+ // Add Settings Page for this Plugin
166
+ global $jr_mt_plugin_data;
167
+ add_theme_page( $jr_mt_plugin_data['Name'], 'Multiple Themes plugin', 'switch_themes', 'jr_mt_settings', 'jr_mt_settings_page' );
168
+ add_options_page( $jr_mt_plugin_data['Name'], 'Multiple Themes plugin', 'switch_themes', 'jr_mt_settings', 'jr_mt_settings_page' );
169
+ }
170
+
171
+ add_action( 'admin_init', 'jr_mt_register_settings' );
172
+ function jr_mt_register_settings() {
173
+ register_setting( 'jr_mt_settings', 'jr_mt_settings', 'jr_mt_validate_settings' );
174
  }
 
 
 
175
  }
 
 
 
 
 
 
 
 
 
 
 
176
 
177
+ if ( is_admin() ) {
178
+ /* && isset( $_GET['page'] ) && ( 'jr_mt_settings' === $_GET['page'] )
179
+ should work, but redirects Save Changes to options.php
180
+ */
181
+ require_once( jr_mt_path() . 'includes/admin-functions.php' );
182
+ /* Admin panel
183
+ */
184
+ require_once( jr_mt_path() . 'includes/admin.php' );
185
+ } else {
186
+ require_once( jr_mt_path() . 'includes/select-theme.php' );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
187
  }
188
  }
189
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
190
  ?>
js/index.html ADDED
File without changes
js/sticky.js ADDED
@@ -0,0 +1,137 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* When the page has fully loaded,
2
+ check if the Plugin's cookie is present
3
+ and decipher it into values that will
4
+ control processing:
5
+ an array consisting of:
6
+ - keyword=value query to append to URL
7
+ - FALSE if Setting "append if question mark ("?") not present", or
8
+ TRUE if Setting "append if another Override query not present"
9
+ - an array of all sticky or override queries (empty array if FALSE)
10
+ If cookie is present, look at all <a> tag href= URLs.
11
+ Restriction: ignore all Relative URLs - those without ://
12
+ For each one, check if it is in the current WordPress site,
13
+ but not in Admin panels (/wp-admin/):
14
+ - strip up to and including ://
15
+ - convert to lower-case
16
+ - if present, strip leading www.
17
+ - convert \ to /
18
+ - remove trailing / of Home URL and Site Admin URL
19
+ If so, append the current Query (keyword=value) specified in
20
+ the plugin's Cookie, to the href= URL, except when:
21
+ - a ? is present in the URL if the plugin Setting is set to that;
22
+ - an override query is already present in the URL, if the plugin
23
+ Setting allows ? in the URL
24
+ - the same sticky query is already present in the URL
25
+ Appending a Query to the URL is done by:
26
+ - inserting it before any # (Fragment, i.e. - Bookmark) in the URL
27
+ - appending to URL otherwise
28
+ - prefixed by ? is ? is not already present
29
+ - prefixed by & if ? is already present
30
+ In addition, hidden text in the HTML provides:
31
+ - WordPress Site Address (URL)
32
+ - WordPress /wp-admin/ URL
33
+ These values are not available for the Cookie, because WordPress must be
34
+ loaded before these values are available.
35
+
36
+ Whether pre-processed in PHP when passed, or within this JavaScript,
37
+ all comparisons are effectively case-insensitive, by converting
38
+ all values to lower-case.
39
+
40
+ Version 6.0 - this code has not been upgraded to support Site Aliases!
41
+ */
42
+ window.onload =
43
+ function ( ) {
44
+ var allCookies, keywordMatch, pos, valueStart, cookieArray, query, homeUrl, siteAdmin, appendSetting, overrideQueries, overrideQueriesEmpty, hrefs, i, max, href, colonSlashSlash, hrefCompare, addQuery, posQuestionMark, posNumberSign, hrefQueries,
45
+ cookieEquals = 'jr-mt-remember-query=',
46
+ cookieSplit = '; ';
47
+
48
+ /* Check if there are any Cookies at all.
49
+ */
50
+ if ( '' !== allCookies ) {
51
+ allCookies = cookieSplit + document.cookie + cookieSplit;
52
+ keywordMatch = cookieSplit + cookieEquals;
53
+ pos = allCookies.indexOf( keywordMatch );
54
+ /* Check if our cookie is present.
55
+ */
56
+ if ( -1 !== pos ) {
57
+ valueStart = pos + keywordMatch.length;
58
+ /* Extract Value of Cookie, which is found after the equals sign and before the semicolon
59
+ */
60
+ cookieArray = JSON.parse( decodeURIComponent( allCookies.substring( pos + keywordMatch.length, allCookies.indexOf( cookieSplit, pos + cookieSplit.length ) ) ) );
61
+ /* Assign Cookie array elements to meaningfully-named variables.
62
+ */
63
+ query = cookieArray[0];
64
+ appendSetting = cookieArray[1];
65
+ overrideQueries = cookieArray[2];
66
+ overrideQueriesEmpty = ( 0 === overrideQueries.length );
67
+
68
+ homeUrl = document.getElementById( 'jr-mt-home-url' )['title'];
69
+ siteAdmin = document.getElementById( 'jr-mt-site-admin' )['title'];
70
+
71
+ hrefs = document.getElementsByTagName ( 'a' );
72
+ for ( i = 0, max = hrefs.length; i < max; i++ ) {
73
+ href = hrefs [ i ] ['href'];
74
+ colonSlashSlash = href.indexOf( '://' );
75
+ /* Ignore Relative URLs: those without ://
76
+ */
77
+ if ( -1 !== colonSlashSlash ) {
78
+ hrefCompare = href.substring( colonSlashSlash + 3 ).toLowerCase();
79
+ if ( 'www.' === hrefCompare.substring( 0, 4 ) ) {
80
+ hrefCompare = hrefCompare.substring( 4 );
81
+ }
82
+ hrefCompare = hrefCompare.replace( /\\/g, '/' );
83
+ addQuery = '';
84
+ if ( hrefCompare.substring( 0, homeUrl.length ) === homeUrl ) {
85
+ if ( hrefCompare.substring( 0, siteAdmin.length ) !== siteAdmin ) {
86
+ posQuestionMark = href.indexOf( '?' );
87
+ posNumberSign = href.indexOf( '#' );
88
+ if ( -1 === posNumberSign ) {
89
+ posNumberSign = href.length;
90
+ }
91
+ /* Only add a Query if one does not already exist.
92
+ */
93
+ if ( -1 === posQuestionMark ) {
94
+ /* Query must be before the Fragment (#anchor),
95
+ when one exists.
96
+ */
97
+ addQuery = '?';
98
+ } else {
99
+ /* Query exists because "?" found in URL.
100
+ Check if setting set to add query when one already exists.
101
+ If not, don't touch this URL.
102
+ */
103
+ if ( appendSetting ) {
104
+ addQuery = '&';
105
+ hrefQueries = href.substring( posQuestionMark + 1, posNumberSign ).split( '&' );
106
+ /* Don't append Sticky query if it is already present in the URL
107
+ */
108
+ if ( -1 !== hrefQueries.indexOf( query ) ) {
109
+ addQuery = '';
110
+ } else {
111
+ if ( !overrideQueriesEmpty ) {
112
+ for ( j = 0, hrefQueriesLength = hrefQueries.length; j < hrefQueriesLength; j++ ) {
113
+ /* Don't append Sticky query if an Override query is present in URL
114
+ */
115
+ if ( -1 !== overrideQueries.indexOf( hrefQueries[ j ].toLowerCase() ) ) {
116
+ /* Override query already in URL.
117
+ */
118
+ addQuery = '';
119
+ break;
120
+ }
121
+ }
122
+ }
123
+ }
124
+ }
125
+ }
126
+ }
127
+ }
128
+ if ( '' !== addQuery ) {
129
+ /* No override or sticky query already in URL, so safe to add current sticky query.
130
+ */
131
+ hrefs [ i ] ['href'] = href.substring( 0, posNumberSign ) + addQuery + query + href.substring( posNumberSign );
132
+ }
133
+ }
134
+ }
135
+ }
136
+ }
137
+ };
js/tabs.js ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* Hide all but the Tab selected.
2
+ <div> is used in the HTML to enclose the HTML peculiar to a Tab,
3
+ with id=jr-mt-settingsn where the last "n" is a unique number from 1 to the number of Tabs.
4
+ onClick is used on a <a> to activate this function.
5
+
6
+ Bold only the Tab selected,
7
+ actually it is Bolder and Bold, instead of Bold and Normal.
8
+ */
9
+ function jrMtTabs( tab, ntabs ) {
10
+ for ( i = 1; i <= ntabs; i++ ) {
11
+ if ( i === tab ) {
12
+ show = 'block';
13
+ classes = 'nav-tab nav-tab-active';
14
+ } else {
15
+ show = 'none';
16
+ classes = 'nav-tab';
17
+ }
18
+ document.getElementById( 'jr-mt-settings' + i ).style.display = show;
19
+ document.getElementById( 'jr-mt-tabs' + i ).className = classes;
20
+ }
21
+ };
readme.txt CHANGED
@@ -1,131 +1,84 @@
1
- === jonradio Multiple Themes ===
2
  Contributors: dgewirtz
3
- Donate link: http://zatzlabs.com/plugins/
4
  Tags: themes, theme, sections, style, template, stylesheet, accessibility
5
- Requires at least: 3.4.1
6
- Tested up to: 3.6
7
- Stable tag: 4.0.2
8
  License: GPLv2 or later
9
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
10
 
11
- Select different Themes for one or more, or all WordPress Pages, Posts or other non-Admin pages. Or Site Home.
12
 
13
  == Description ==
14
 
15
- Allows the Administrator to specify which Theme will be used on specific Pages, Posts, other non-Admin pages (such as Category or Archive pages) or Site Home. Also allows a Theme to be specified for All Pages or All Posts. In turn, even when a Theme is specified for All Pages or All Posts, a different Theme can still be specified for specific Pages or Posts.
16
 
17
- Think what you could do if you could easily use more than one Theme on your WordPress web site or blog:
18
 
19
- * Divide your site into Sections, each with its own unique look
20
- * Style individual Pages, Posts, or other elements (Site Home, Category main page, Archive main page) with a different Theme
21
- * Select a unique Theme for all Pages, Posts, Attachments, Category pages or Archive pages
22
- * Make slight variations to a Theme, using Child Themes, for one or more Pages, Posts or other elements (Site Home, Category main page, Archive main page)
23
- * Supports Multiple Stylesheets for Accessibility and other purposes (create one Child Theme for each Stylesheet)
24
- * Test a new Theme on one or more Pages or Posts
25
- * Convert to a new Theme a Page or Post at a time
26
- * Host multiple mini-web sites on your WordPress site, each with a different Theme
27
- * When a larger version of an image attachment is displayed, for example, when clicking on a gallery image thumbnail, use a different theme to display it, for one or all images attached to a Page or Post
28
 
29
- **Use with other Plugins**: **BuddyPress** and Theme Test Drive plugins must both be Deactivated when jonradio Multiple Themes is Activated
 
 
 
 
 
 
 
 
 
30
 
31
- **Changing Theme Options (Widgets, Sidebars, Menus, Templates, Background, Header, etc.)?**: See the FAQ (Frequently-Asked Questions) tab for important information and warnings on changing Options on Themes other than the Current Theme.
32
 
33
- To select all Pages, Posts, Archives, Categories, etc. that begin with the same partial URL, a "Prefix URL" can be specified by selecting the Prefix checkbox when creating an entry on the Settings page for the jonradio Multiple Themes plugin. Restriction: the Prefix URL cannot contain all or part of a Query, which is the portion of a URL that begins with a question mark ("?"). Although the Prefix cannot contain a Query, URLs containing a Query will be matched by the Prefix.
34
 
35
- If a Theme is not specified for a Page, Post, Site Home or other WordPress-displayed web page, such as Category or Archive display, the **Current Theme** specified in **Appearance-Themes** on the Admin panels will be used.
36
 
37
- When selecting a Theme for Site Home or all or specific Pages, Posts or other non-Admin pages, the Theme must be shown in the list of Available Themes on the Appearance-Themes Admin panel. If necessary, install the Theme. In a WordPress Network (AKA Multisite), Themes must be **Network Enabled** before they will appear as Available Themes on individual sites' Appearance-Themes panel.
38
 
39
- I hesitate to use the term **Theme Switcher** to describe this plugin, because the term has so many meanings. The jonradio Multiple Themes plugin does **not** alter the standard WordPress options that define what Theme is used on your WordPress site. Instead, it dynamically (and selectively) overrides that choice. Technical details aside, what this means is that deactivating or deleting the jonradio Multiple Themes plugin will instantly revert to the WordPress Current Theme that you have defined through the standard WordPress Appearance-Themes Admin panel.
40
 
41
- == Installation ==
42
-
43
- This section describes how to install the jonradio Multiple Themes plugin and get it working.
44
-
45
- 1. Use "Add Plugin" within the WordPress Admin panel to download and install this jonradio Multiple Themes plugin from the WordPress.org plugin repository (preferred method). Or download and unzip this plugin, then upload the `/jonradio-multiple-themes/` directory to your WordPress web site's `/wp-content/plugins/` directory.
46
- 1. Activate the jonradio Multiple Themes plugin through the 'Plugins' menu in WordPress. If you have a WordPress Network ("Multisite"), you can either Network Activate this plugin, or Activate it individually on the sites where you wish to use it. Activating on individual sites within a Network avoids some of the confusion created by WordPress' hiding of Network Activated plugins on the Plugin menu of individual sites.
47
- 1. Be sure that all Themes you plan to use have been installed and are listed under Available Themes on the WordPress Appearance-Themes Admin panel. In a WordPress Network (AKA Multisite), Themes must be **Network Enabled** before they will appear as Available Themes on individual sites' Appearance-Themes panel.
48
- 1. Select Themes to be used on the Plugin's "Multiple Themes plugin" page in the WordPress Admin panels, which is found in both the **Appearance** and **Settings** sections. You can also get to this page by clicking on the **Settings** link for this plugin on the **Installed Plugins** page.
49
- 1. If you need to change Theme Options (Widgets, Sidebars, Menus, Templates, Background, Header, etc.) for any Theme other than the Current Theme, see the FAQ (Frequently-Asked Questions) tab for important information and warnings.
50
-
51
- == Frequently Asked Questions ==
52
-
53
- = Will this plugin work with Paid Themes? =
54
-
55
- Yes, in most cases. But we have only tested the few Paid Themes whose authors have provided us with permission to use, without charge, their themes for test purposes. Elegant, for example, allows us to accept copies of its Themes provided by its customers who require assistance with the jonradio Multiple Themes plugin. On the other hand, some other Paid Theme authors have simply ignored our requests, despite our stated willingness to sign a non-disclosure agreement.
56
-
57
- We do encourage you to contact us if you run into problems when using the jonradio Multiple Themes plugin with a Paid Theme, as the problem may not be unique to the Paid Theme.
58
 
59
- To state the obvious, the cost of purchasing a license for all Paid Themes for testing purposes is prohibitive for an Open Source plugin such as this one.
 
60
 
61
- = How do I change the Theme Options (Widgets, Sidebars, Menus, Background, Header, etc.) used for each Theme? =
62
 
63
- **NOTE**: See the next FAQ for information on Templates.
64
-
65
- **WARNING**: It is not currently possible to have separate Widgets **AND** Menus for multiple Themes using the current version of this Plugin. The only known solution to this problem is to have multiple WordPress sites, either as a separate WordPress installation or as part of a WordPress Network using its Multisite feature. This can be done on the same domain name using either folders/subdirectories or subdomains. Each site would then have just one Theme, and you would not require this Plugin.
66
-
67
- For the Current Theme, nothing changes when using the jonradio Multiple Themes plugin. Options for the Current Theme, including Widgets, Sidebars, Menus, Background, Header and other Customizations supported by the Theme, can be modified in the Admin panel using the Appearance menu items on the left sidebar and the Customize link displayed beside the Current Theme on the Manage Themes tab of Appearance-Themes.
68
 
69
- It is more difficult to modify Options for Active Themes that are *not* the Current Theme. We hope to build this functionality into the jonradio Multiple Themes plugin in a future Version, but it is not clear just how practical that is, so the best that can be said is: Maybe.
70
 
71
- For now, there are two approaches. Except for Widgets, the first approach is the most likely to give you success. Menus, on the other hand, really work well with the first approach, and are severely restricted with the second method.
 
 
 
 
72
 
73
- **WARNING**: So far, we have not received any reports of, nor have we tested, using both Method #1 and #2 on the same WordPress site. Use Caution if you plan to do so, as we cannot predict the results.
74
 
75
- **Method #1:**
76
 
77
- Set the Theme Options with Live Preview.
78
 
79
- Note: Widgets cannot be placed using this Method.
80
 
81
- 1. Go to Appearance-Themes-Live Preview in the Admin panels.
82
- 1. Use the right sidebar to modify the Theme Options. Note that "Navigation" will not appear until a Custom Menu has been defined in Appearance-Menus. Navigation-Primary Navigation is where you would set the custom menu to be used for the Theme you are currently previewing.
83
- 1. Click the Save & Activate button.
84
- 1. Go immediately to Appearance-Themes to reactivate the Current Theme.
85
 
86
- **Method #2:**
87
 
88
- Use the Theme Test Drive plugin.
89
 
90
- Note: this approach only allows Menus to be set for one Theme. Using this method to assign one or more menus to a Theme will unassign menus for all other Themes.
91
 
92
- The jonradio Multiple Themes plugin (i.e. - this plugin) must be Deactivated, and the Theme Test Drive plugin installed and activated, so that each Theme can be selected with the Theme Test Drive plugin, allowing the Theme's Options to be set "as if" it were the Current Theme.
93
 
94
- 1. Deactivate jonradio Multiple Themes
95
- 1. Install the Theme Test Drive plugin found at http://wordpress.org/extend/plugins/theme-test-drive/
96
- 1. Activate the Theme Test Drive plugin
97
- 1. Go to Appearance-Theme Test Drive
98
- 1. In the Usage section, select an alternate Theme you will be using with jonradio Multiple Themes
99
- 1. Push the Enable Theme Drive button at the bottom
100
- 1. Go to the WordPress Admin panel's Appearance menu (left sidebar)
101
- 1. Make your changes to the Theme Options, including Widgets, Sidebars, Menus (see note above about Menus), Background, Header and other Customizations for this alternate Theme (which will appear as if it were the Current Theme)
102
- 1. If you have more than one alternate Theme with Options you wish to change, repeat Steps 4-8 for each alternate Theme
103
- 1. Deactivate the Theme Test Drive plugin
104
- 1. Activate jonradio Multiple Themes
105
- 1. Changes to the Options for the Current Theme can now be made normally, just as you would without either plugin
106
- 1. Both the alternate and Current Themes should now display all Theme options properly when selected through the jonradio Multiple Themes plugin
107
 
108
  = How do I change the Template for a specific Page or Post? =
109
 
110
- For the Current Theme, nothing changes when using the jonradio Multiple Themes plugin. Select an alternate Template from the drop-down list in the Template field of the Page Attributes section of the Add New Page, Edit Page, Add New Post or Edit Post page of the Admin panels. Or the Template field in Quick Edit.
111
-
112
- It is more difficult to change Templates for Pages or Posts defined with the jonradio Multiple Themes plugin to use Active Themes that are *not* the Current Theme. We hope to build this functionality into the jonradio Multiple Themes plugin in a future Version.
113
-
114
- Use the Theme Test Drive plugin. The jonradio Multiple Themes plugin (i.e. - this plugin) must be Deactivated, and the Theme Test Drive plugin installed and activated, so that each Theme can be selected with the Theme Test Drive plugin, allowing the Theme's Template to be set for each Page or Post using that Theme "as if" it were the Current Theme.
115
-
116
- 1. Deactivate jonradio Multiple Themes
117
- 1. Install the Theme Test Drive plugin found at http://wordpress.org/extend/plugins/theme-test-drive/
118
- 1. Activate the Theme Test Drive plugin
119
- 1. Go to Appearance-Theme Test Drive
120
- 1. In the Usage section, select an alternate Theme you will be using with jonradio Multiple Themes
121
- 1. Push the Enable Theme Drive button at the bottom
122
- 1. Go to the WordPress Admin panel's Page or Post menu (left sidebar)
123
- 1. Make your changes to the Template field of each Page and/or Post that has been selected for this alternate Theme AND requires a non-default Template
124
- 1. If you have more than one alternate Theme with Templates you wish to change, repeat Steps 4-8 for each alternate Theme
125
- 1. Deactivate the Theme Test Drive plugin
126
- 1. Activate jonradio Multiple Themes
127
- 1. Changes to the Templates for Pages and Posts using the Current Theme can now be made normally, just as you would without either plugin
128
- 1. Both the alternate and Current Themes should now display all Templates properly when selected through the jonradio Multiple Themes plugin
129
 
130
  = How do I select a Theme for a Category of Posts? =
131
 
@@ -176,23 +129,165 @@ Thanks to Elegant for allowing us to test copies of any of their Themes provided
176
 
177
  = What happens when I change Permalinks? =
178
 
179
- For entries you have created for individual Pages and Posts with the jonradio Multiple Themes plugin, you can subsequently change your Permalink structure or you can change the Permalink of a Page or Post, without having to change the plugin's entry. However, for other pages, such as Categories or Archives, you will have to delete your old entries and create new ones with the jonradio Multiple Themes plugin.
180
 
181
  = I added a new entry but why doesn't it appear in the list of entries? =
182
 
183
- If you add an entry that already exists, it merely replaces the previous entry.
184
 
185
  = How can I change the Theme for an entry? =
186
 
187
- Simply add the entry again, with the new Theme. It will replace the previous entry.
188
 
189
  == Screenshots ==
190
 
191
- 1. Plugin's Admin Page when first installed
192
- 2. Plugin's Admin Page, adding entries
 
 
 
 
193
 
194
  == Changelog ==
195
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
196
  = 4.0.2 =
197
  * Prevent Warning and Notice by initializing global $wp
198
 
@@ -240,6 +335,102 @@ Simply add the entry again, with the new Theme. It will replace the previous en
240
 
241
  == Upgrade Notice ==
242
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
243
  = 4.0.2 =
244
  Fix "Warning: in_array() expects parameter 2 to be array, null given in domain.com/wp-includes/rewrite.php on line 364"
245
 
1
+ === Multiple Themes ===
2
  Contributors: dgewirtz
3
+ Donate link: http://zatzlabs.com/lab-notes/
4
  Tags: themes, theme, sections, style, template, stylesheet, accessibility
5
+ Requires at least: 3.4
6
+ Tested up to: 4.3
7
+ Stable tag: 7.1
8
  License: GPLv2 or later
9
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
10
 
11
+ Select different Themes for one or more WordPress Pages, Posts or other non-Admin pages. Or Site Home.
12
 
13
  == Description ==
14
 
15
+ **Version 7 adds exhaustive checking and correction of the plugin's Settings that may have become corrupted**
16
 
17
+ *Formerly: "jonradio Multiple Themes"*
18
 
19
+ Settings provide many different ways to Select which Theme should appear where on your WordPress web site:
 
 
 
 
 
 
 
 
20
 
21
+ * Just for Site Home
22
+ * By URL (Version 5 adds support for Query keyword=value as part of a unique URL);
23
+ * By Prefix URL, matching all URLs that begin with the same characters ("Prefix URL");
24
+ * By Wildcard Prefix URL with one or more Asterisks ("*") representing arbritrary subdirectories in the URL;
25
+ * By Query Keyword found in any URL, not matter what the Value;
26
+ * By Query keyword=value found in any URL;
27
+ * By Sticky Query keyword=value that sets the Theme for a given Visitor until an Override Query keyword=value is found in a future URL (Advanced Setting requiring the Visitor's browser to accept Cookies; incompatible with certain plugins that block Cookies);
28
+ * Everywhere (Advanced Setting that overrides the WordPress Active Theme);
29
+ * All Pages (Advanced Setting that works with most, but not all, Themes and Plugins);
30
+ * All Posts (Advanced Setting that works with most, but not all, Themes and Plugins).
31
 
32
+ None of the Themes in the WordPress Theme Directory alter the appearance of the WordPress Admin panels. As a result, this plugin does not allow Theme Selection entries to specify URLs for WordPress Admin panels.
33
 
34
+ **Use with Paid Themes**: On-going full scale testing of Themes by this plugin's author is only possible if the Theme is found in the WordPress Theme Directory. Although (Version 5 of) this plugin should now work with all Themes, any problems encountered while using Paid Themes will be difficult to diagnose. As described in the FAQ tab, a WordPress Network (Multisite) is an alternative to this plugin, as a way to create a single web site with more than one Theme.
35
 
36
+ A similar situation exists with Paid Plugins.
37
 
38
+ **Use with Plugins that Cache**: You may find that you have to flush the Cache whenever you change Settings in the *jonradio Multiple Themes* plugin. Some Caching plugins only cache for visitors who are not logged in as users, so be sure to log out before testing the results of your *jonradio Multiple Themes* settings.
39
 
40
+ **Changing Theme Options (Widgets, Sidebars, Menus, Templates, Background, Header, etc.)?**: After installing and activating the plugin, see the plugin's Settings page and click on the **Theme Options** tab for important information on changing Options for Themes other than the Active Theme.
41
 
42
+ **How it Works**: The plugin does not change the Active Theme defined to WordPress in the Appearances-Themes Admin panel. Instead, it dynamically (and selectively) overrides that setting. Which means that simply deactivating (or deleting) this plugin will restore the way that Themes were displayed prior to installing this plugin. However, in some situations, it is possible to inadvertently alter Theme Options for the Active Theme when using either of the Methods described on the plugin's Setting page Theme Options tab.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
43
 
44
+ > <strong>Adoption Notice</strong><br>
45
+ > This plugin was recently adopted by David Gewirtz and ongoing support and updates will continue. Feel free to visit [David's Lab Notes](http://zatzlabs.com/lab-notes/) for additional details and to sign up for emailed news updates.
46
 
47
+ Special thanks to Jon 'jonradio' Pearkins for creating the plugin and making adoption possible.
48
 
49
+ == Installation ==
 
 
 
 
50
 
51
+ This section describes how to install the *jonradio Multiple Themes* plugin and get it working.
52
 
53
+ 1. Use **Add Plugin** within the WordPress Admin panel to download and install this *jonradio Multiple Themes* plugin from the WordPress.org plugin repository (preferred method). Or download and unzip this plugin, then upload the `/jonradio-multiple-themes/` directory to your WordPress web site's `/wp-content/plugins/` directory.
54
+ 1. Activate the *jonradio Multiple Themes* plugin through the **Installed Plugins** Admin panel in WordPress. If you have a WordPress Network ("Multisite"), you can either **Network Activate** this plugin through the **Installed Plugins** Network Admin panel, or Activate it individually on the sites where you wish to use it. Activating on individual sites within a Network avoids some of the confusion created by WordPress' hiding of Network Activated plugins on the Plugin menu of individual sites. Alternatively, to avoid this confusion, you can install the *jonradio Reveal Network Activated Plugins* plugin.
55
+ 1. Be sure that all Themes you plan to use have been installed.
56
+ 1. Select Themes to be used on the Settings or Advanced Settings tab of the plugin's **Multiple Themes plugin** Settings page in the WordPress Admin panels, which is found in both the **Appearance** and **Settings** sections. You can also get to this Settings page by clicking on the **Settings** link for this plugin on the **Installed Plugins** page of the Admin panel.
57
+ 1. If you need to change Theme Options (Widgets, Sidebars, Menus, Templates, Background, Header, etc.) for any Theme *other than* the Active Theme, see the plugin's Settings page and click on the **Theme Options** tab for important information.
58
 
59
+ == Frequently Asked Questions ==
60
 
61
+ = What if my Themes or other plugins don't seem to be working with the jonradio Multiple Themes plugin? =
62
 
63
+ Please ask before giving up. Either by [posting a Support question](http://wordpress.org/support/plugin/jonradio-multiple-themes "Support Forum") or contacting us directly by filling out this [Contact Form (click here)](http://zatzlabs.com/contact-us/ "Contact Form").
64
 
65
+ If we cannot solve the problem, please consider using a WordPress Network. One install of WordPress allows you to have multiple separate Sites ("MultiSite"), each with a different Theme, without using the jonradio Multiple Themes plugin. The sites can look to the outside world as if they are just one web site by using the Sub-directories option. For example, Site 1 would be at example.com, and Site 2 could be at example.com/forum.
66
 
67
+ = Will this plugin work with Paid Themes? =
 
 
 
68
 
69
+ With the massive rewrite of Theme Selection logic in Version 5 of this plugin, it should now work with all Paid Themes and Plugins. But we have only tested the few Paid Themes whose authors have provided us with permission to use, without charge, their themes for test purposes. Elegant, for example, allows us to accept copies of its Themes provided by its customers who require assistance with the jonradio Multiple Themes plugin. On the other hand, some other Paid Theme authors have simply ignored our requests, despite our stated willingness to sign a non-disclosure agreement.
70
 
71
+ We do encourage you to contact us if you run into problems when using the jonradio Multiple Themes plugin with a Paid Theme, as the problem may not be unique to the Paid Theme.
72
 
73
+ To state the obvious, the cost of purchasing a license for all Paid Themes for testing purposes is prohibitive for an Open Source plugin such as this one.
74
 
75
+ = How do I change the Theme Options (Widgets, Sidebars, Menus, Background, Header, etc.) used for each Theme? =
76
 
77
+ For the Active Theme, nothing changes when using the jonradio Multiple Themes plugin. For other Themes, selected using this plugin, changing Theme Options is explained, in detail, on the Theme Options tab of the plugin's Settings page.
 
 
 
 
 
 
 
 
 
 
 
 
78
 
79
  = How do I change the Template for a specific Page or Post? =
80
 
81
+ For the Current Theme, nothing changes when using the jonradio Multiple Themes plugin. For a Page or Post where another Theme is displayed, as selected by this plugin's Settings, specifying the Template to be used is explained, in detail, on the Theme Options tab of the plugin's Settings page.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
82
 
83
  = How do I select a Theme for a Category of Posts? =
84
 
129
 
130
  = What happens when I change Permalinks? =
131
 
132
+ Although it depends on what kind of change you make to your Permalink structure, you should expect to have to replace (delete and add) all of the plugin's Settings that specify a URL.
133
 
134
  = I added a new entry but why doesn't it appear in the list of entries? =
135
 
136
+ You should have seen an explanatory error message after hitting the Save Changes button.
137
 
138
  = How can I change the Theme for an entry? =
139
 
140
+ You will need to delete the entry and add it again, with the new Theme specified.
141
 
142
  == Screenshots ==
143
 
144
+ 1. Top of Settings tab on Plugin's Settings page
145
+ 2. Bottom of Settings tab on Plugin's Settings page
146
+ 3. Advanced Settings tab on Plugin's Settings page
147
+ 4. Theme Options tab on Plugin's Settings page
148
+ 5. System Information tab on Plugin's Settings page
149
+ 6. New in V5 tab on Plugin's Settings page
150
 
151
  == Changelog ==
152
 
153
+ = 7.1 =
154
+ * Very Simple AJAX Support: select a theme whenever /wp-admin/admin-ajax.php is accessed by URL
155
+ * Remove P2 Theme automatic handling as it no longer works with current version of P2 Theme
156
+
157
+ = 7.0.3 =
158
+ * Fix All Posts and All Pages setting's url_to_postid() function issues introduced in 7.0.2
159
+
160
+ = 7.0.2 =
161
+ * Fix Port URL matching issue
162
+
163
+ = 7.0.1 =
164
+ * Fix Query Matching when Value is an Integer in Query Settings
165
+
166
+ = 7.0 =
167
+ * Check and cleanup Settings on every viewing of the Settings page, to maximize compatibility with previous versions
168
+ * Store PostID as String instead of Integer in URL Settings so it will match incoming URL with p=id, etc.
169
+ * Make sure that both Query Keyword and Value are never any Numeric type, but always String
170
+ * Correct numerous small bugs
171
+
172
+ = 6.0.2 =
173
+ * Fix bug that stripped off Queries in URL Settings
174
+
175
+ = 6.0.1 =
176
+ * Store $wp->public_query_vars in Internal Settings for use before 'init' action
177
+ * Tolerate missing $_SERVER['QUERY_STRING']
178
+
179
+ = 6.0 =
180
+ * Add URL Alias settings
181
+ * Move "Settings" link to beginning of links on Installed Plugins Admin page
182
+
183
+ = 5.0.3 =
184
+ * Remove Cleanup code for Settings for non-existent Themes, as it conflicts with delete/reinstall theme version upgrades, and certain caching plugins
185
+
186
+ = 5.0.2 =
187
+ * Remove /downgrade/ directory in case it caused the reported PCLZIP_ERR_BAD_FORMAT errors
188
+
189
+ = 5.0.1 =
190
+ * Fix All Pages and All Posts by complete rewrite of Theme Selection logic for those Advanced Settings
191
+
192
+ = 5.0 =
193
+ * Major rewrite of the Theme Selection logic
194
+ * Tabs added to the Settings page, for easier navigation
195
+ * Greatly expanded compatibility with other Plugins and Themes
196
+ * Allow ?keyword=value&keyword=value Queries in URL, URL Prefix and URL Prefix with Asterisk ("*") Theme Selection entries
197
+ * Accurate Theme Selection even for plugins and themes that request Stylesheet or Template information before WordPress is fully loaded
198
+ * Tabs for the Setting page written in JavaScript for instant switching between tabs and preservation of input data, e.g. - switch between Settings and Advanced Settings tabs without having to retype your changes when you switch back
199
+ * Theme Selection entries, if any, displayed in the order in which they are processed, to clarify which Theme will be displayed for any given URL
200
+ * Complete How-To details on Theme Option and Template selection right on the Settings page, replacing the FAQs in the WordPress Plugin Directory
201
+ * Automatic deletion of Theme Selection entries for Themes that have been deleted
202
+ * Enhanced performance with tighter code, and less of it, on the public side of your WordPress site
203
+ * Changing Permalinks invalidates more Theme Selection settings than in previous versions
204
+ * Changing the Theme for an Entry requires Deletion of the old Entry before or after adding the same Entry with the new Theme specified
205
+ * The new Theme Selection logic, based on URL Matching rather than Page, Post, Attachment, Category and Archive IDs, requires a conversion of some Settings from prior versions of the plugin. This conversion to the new format occurs automatically the first time that Version 5 runs. Old format settings are retained, transparently without being displayed on the Settings page, to allow downgrading to Version 4 from Version 5.
206
+
207
+ = 4.11.3 =
208
+ * Fix Array to String Warning on some Search plugins by rewriting jt_mt_themes_defined() which creates list of Themes referenced in plugin Settings
209
+ * Add More Diagnostic Information to Settings page
210
+ * Suggest "URL Prefix" setting when "URL" setting does not work, especially for WooCommerce
211
+ * Detect Memberium plugins and explain that Sticky will not work with Membership System V2 because it blocks Cookies
212
+ * Add Warning and change one confusing Error Message when Query is incorrectly included in URL of Page/Post entry
213
+
214
+ = 4.11.2 =
215
+ * Made all Query comparisons (URL match Setting) case insensitive
216
+ * Eliminate Connection Info prompt from Settings page that occurred for certain User Permissions
217
+ * Add File Permissions table to Settings
218
+
219
+ = 4.11.1 =
220
+ * Correct foreach() error
221
+
222
+ = 4.11 =
223
+ * Complete Rewrite of Sticky logic, adding additional Settings, including Override
224
+
225
+ = 4.10.1 =
226
+ * Sticky: add a unique Query to URL so that Caching plugins will cache separate copies for each Theme used on a particular page
227
+
228
+ = 4.10 =
229
+ * Add a Sticky option (Advanced Setting) for URL Queries (keyword=value) that will select the same Theme for all subsequent pages viewed by the same Visitor
230
+ * Enhance performance by eliminating processing related to each Type of Setting when no Setting entries of that Type exist
231
+
232
+ = 4.9 =
233
+ * Add an Asterisk ("*") to match any Subdirectory at a given level of the File Hierarchy, as another form of the Prefix URL option
234
+ * Reorganize Settings page
235
+
236
+ = 4.8 =
237
+ * Delay intercept of get_options 'stylesheet' and 'template' until 'plugins_loaded' (NextGen Gallery conflict)
238
+ * Check for illegal characters in Keyword and Value of Query portion of URL in Settings fields
239
+
240
+ = 4.7.3 =
241
+ * Add support for dot in URL Queries (keyword or value) by replacing parse_str()
242
+ * Removed subfolder /includes/debug/
243
+
244
+ = 4.7.2 =
245
+ * Do not execute select-theme.php on Admin panels, to eliminate error message whenever any plugin is uninstalled
246
+ * Handle URL Query Keyword[]=Value
247
+ * Add Polylang to list of incompatible plugins
248
+
249
+ = 4.7.1 =
250
+ * Handle PHP without mbstring extension
251
+
252
+ = 4.7 =
253
+ * Add option to select a Theme based on Query Keyword and Value pair in URL
254
+ * Redesign how Query entries are stored
255
+ * Full testing completed with WordPress Version 3.8
256
+
257
+ = 4.6 =
258
+ * Add option to select a Theme based on Query Keyword in URL
259
+ * Rearrange Settings page
260
+
261
+ = 4.5.2 =
262
+ * Eliminate Fatal Error if php zip_open() function is not available, when readme.txt is out of date
263
+
264
+ = 4.5.1 =
265
+ * Remove %E2%80%8E suffix from URLs being entered
266
+
267
+ = 4.5 =
268
+ * Check with get_page_by_path() and get_posts( array( 'name' => $page_url ) ) if url_to_postid() fails to find URL input
269
+
270
+ = 4.4 =
271
+ * Rewrite Plugin's handling of its own version number to fix issues when new sites are activated in a Network and plugin is Network-Activated
272
+ * Prevent Fatal Error for Versions of WordPress before 3.4, and Deactivate Plugin instead, because plugin requires at least 3.4 to function
273
+ * Security: require "switch_themes" Capability rather than "manage_options" Capability to access plugin's Settings page
274
+
275
+ = 4.3 =
276
+ * Add SSL support so that visitors can view the WordPress site with https:// URLs and Site URL can be https://
277
+
278
+ = 4.2 =
279
+ * Add option to override WordPress Current Theme
280
+ * Security enhancements to eliminate direct execution of .php files
281
+
282
+ = 4.1.1 =
283
+ * Handle situations where readme.txt file in plugin's directory cannot be read or written
284
+
285
+ = 4.1 =
286
+ * Support for non-alphanumeric characters in URLs, e.g. - languages using characters not in the English alphabet
287
+ * Support for Live Search feature of KnowHow Theme
288
+ * Display errors, not settings, on plugin's Admin page for activated BuddyPress or Theme Test Drive plugins, or old versions of WordPress
289
+ * Add error checking/messages and diagnostic information to plugin's Admin page
290
+
291
  = 4.0.2 =
292
  * Prevent Warning and Notice by initializing global $wp
293
 
335
 
336
  == Upgrade Notice ==
337
 
338
+ = 7.1 =
339
+ AJAX Support
340
+
341
+ = 7.0.3 =
342
+ Make All Posts and All Pages settings work on sites without a Port Number specified
343
+
344
+ = 7.0.2 =
345
+ Correct URL Matching for Sites with a Port Number in their URL
346
+
347
+ = 7.0.1 =
348
+ Correctly handle p= and page_id= in Query Settings
349
+
350
+ = 7.0 =
351
+ Checks all Settings whenever Settings page displayed
352
+
353
+ = 6.0.2 =
354
+ Correct bug that stripped Queries from URLs in Settings
355
+
356
+ = 6.0.1 =
357
+ Tolerate missing $_SERVER['QUERY_STRING'] and $wp->public_query_vars not set up yet
358
+
359
+ = 6.0 =
360
+ Support Domain Mapping, Parked Domains and other Site Alias usages
361
+
362
+ = 5.0.3 =
363
+ Remove cleanup of non-existent themes specified in Settings
364
+
365
+ = 5.0.2 =
366
+ Remove /downgrade/ directory that may have caused PCLZIP_ERR_BAD_FORMAT errors on some web hosts
367
+
368
+ = 5.0.1 =
369
+ Correct All Pages and All Posts (Advanced) Setting bug
370
+
371
+ = 5.0 =
372
+ Greatly expanded compatibility with other Plugins and Themes
373
+
374
+ = 4.11.2 =
375
+ Standardize to case insensitive Query comparisons and eliminate Connection Info prompt on Settings page
376
+
377
+ = 4.11.1 =
378
+ Fix foreach() error
379
+
380
+ = 4.11 =
381
+ Complete rewrite of Sticky logic
382
+
383
+ = 4.10.1 =
384
+ Make Sticky work with Caching plugins
385
+
386
+ = 4.10 =
387
+ Performance improvements and add Sticky Queries
388
+
389
+ = 4.9 =
390
+ Allow Prefix URLs to match all subdirectories with an Asterisk ("*")
391
+
392
+ = 4.8 =
393
+ Compatibility with NextGen Gallery plugin
394
+
395
+ = 4.7.3 =
396
+ Allow dots in URL Queries
397
+
398
+ = 4.7.2 =
399
+ Avoid Error Message during Uninstall of other Plugins
400
+
401
+ = 4.7.1 =
402
+ Avoid mb_ function errors for PHP without mbstring extension
403
+
404
+ = 4.7 =
405
+ Select Theme by Query Keyword/Value pair in URL
406
+
407
+ = 4.6 =
408
+ Select Theme by Query Keyword in URL
409
+
410
+ = 4.5.2 =
411
+ Fix zip_open Fatal Error
412
+
413
+ = 4.5.1 =
414
+ Fix %E2%80%8E suffix problem on input URLs
415
+
416
+ = 4.5 =
417
+ Handle URL input for non-standard Pages and Posts
418
+
419
+ = 4.4 =
420
+ Fix errors when new Network site created or old WordPress version used, and correct Setting page Permissions to "switch_themes"
421
+
422
+ = 4.3 =
423
+ Add SSL support for sites with https:// URLs
424
+
425
+ = 4.2 =
426
+ Add "Select Theme for Everything" feature and improve security
427
+
428
+ = 4.1.1 =
429
+ Resolve issues with readme.txt permissions introduced in Version 4.1's compatibility checking
430
+
431
+ = 4.1 =
432
+ Support non-English alphabet in URLs and Live Search feature in KnowHow Theme
433
+
434
  = 4.0.2 =
435
  Fix "Warning: in_array() expects parameter 2 to be array, null given in domain.com/wp-includes/rewrite.php on line 364"
436
 
uninstall.php CHANGED
@@ -1,18 +1,27 @@
1
  <?php
2
- // Ensure call comes from WordPress, not a hacker.
3
  if ( !defined( 'WP_UNINSTALL_PLUGIN' ) )
4
  exit ();
5
 
 
6
  /* Remove any tables, options, and such created by this Plugin */
7
- if ( function_exists('is_multisite') && is_multisite() ) {
 
 
 
 
 
8
  global $wpdb, $site_id;
9
  $blogs = $wpdb->get_results( "SELECT blog_id FROM {$wpdb->blogs} WHERE site_id = $site_id" );
10
- foreach ($blogs as $blog_obj) {
11
- delete_blog_option( $blog_obj->blog_id, 'jr_mt_settings' );
12
- delete_blog_option( $blog_obj->blog_id, 'jr_mt_internal_settings' );
 
13
  }
14
  } else {
15
- delete_option( 'jr_mt_settings' );
16
- delete_option( 'jr_mt_internal_settings' );
 
17
  }
 
18
  ?>
1
  <?php
2
+ // Ensure call comes from WordPress, not a hacker or anyone else trying direct access.
3
  if ( !defined( 'WP_UNINSTALL_PLUGIN' ) )
4
  exit ();
5
 
6
+
7
  /* Remove any tables, options, and such created by this Plugin */
8
+ $setting_names = array(
9
+ 'jr_mt_settings',
10
+ 'jr_mt_internal_settings',
11
+ 'jr_mt_all_themes'
12
+ );
13
+ if ( function_exists( 'is_multisite' ) && is_multisite() ) {
14
  global $wpdb, $site_id;
15
  $blogs = $wpdb->get_results( "SELECT blog_id FROM {$wpdb->blogs} WHERE site_id = $site_id" );
16
+ foreach ( $blogs as $blog_obj ) {
17
+ foreach ( $setting_names as $name ) {
18
+ delete_blog_option( $blog_obj->blog_id, $name );
19
+ }
20
  }
21
  } else {
22
+ foreach ( $setting_names as $name ) {
23
+ delete_option( $name );
24
+ }
25
  }
26
+
27
  ?>