Multiple Themes - Version 4.2

Version Description

  • Add option to override WordPress Current Theme
  • Security enhancements to eliminate direct execution of .php files
Download this release

Release Info

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

Version 4.2

includes/admin-other.php ADDED
@@ -0,0 +1,47 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ // Exit if .php file accessed directly
3
+ if ( !defined( 'ABSPATH' ) ) exit;
4
+
5
+
6
+ add_action( 'all_admin_notices', 'jr_mt_all_admin_notice' );
7
+ // Runs after admin_menu hook
8
+
9
+ function jr_mt_all_admin_notice() {
10
+ if (
11
+ in_array(
12
+ get_current_user_id(),
13
+ get_users(
14
+ array(
15
+ 'role' => 'administrator',
16
+ 'fields' => 'ID'
17
+ )
18
+ )
19
+ )
20
+ )
21
+ {
22
+ // Administrators only see this:
23
+ // echo '<div class="error">Should Show on Every Admin Page</div>';
24
+ }
25
+ }
26
+
27
+ // Add Link to the plugin's entry on the Admin "Plugins" Page, for easy access
28
+ add_filter( 'plugin_action_links_' . jr_mt_plugin_basename(), 'jr_mt_plugin_action_links', 10, 1 );
29
+
30
+ /**
31
+ * Creates Settings entry right on the Plugins Page entry.
32
+ *
33
+ * Helps the user understand where to go immediately upon Activation of the Plugin
34
+ * by creating entries on the Plugins page, right beside Deactivate and Edit.
35
+ *
36
+ * @param array $links Existing links for our Plugin, supplied by WordPress
37
+ * @param string $file Name of Plugin currently being processed
38
+ * @return string $links Updated set of links for our Plugin
39
+ */
40
+ function jr_mt_plugin_action_links( $links ) {
41
+ // The "page=" query string value must be equal to the slug
42
+ // of the Settings admin page.
43
+ array_push( $links, '<a href="' . get_bloginfo('wpurl') . '/wp-admin/admin.php?page=jr_mt_settings' . '">Settings</a>' );
44
+ return $links;
45
+ }
46
+
47
+ ?>
includes/admin.php ADDED
@@ -0,0 +1,647 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ // Exit if .php file accessed directly
3
+ if ( !defined( 'ABSPATH' ) ) exit;
4
+
5
+
6
+ // Admin Page
7
+
8
+ require_once( jr_mt_path() . 'includes/admin-other.php' );
9
+
10
+ add_action( 'admin_menu', 'jr_mt_admin_hook' );
11
+ // Runs just after admin_init (below)
12
+
13
+ /**
14
+ * Add Admin Menu item for plugin
15
+ *
16
+ * Plugin needs its own Page in the Settings section of the Admin menu.
17
+ *
18
+ */
19
+ function jr_mt_admin_hook() {
20
+ // Add Settings Page for this Plugin
21
+ global $jr_mt_plugin_data;
22
+ add_theme_page( $jr_mt_plugin_data['Name'], 'Multiple Themes plugin', 'manage_options', 'jr_mt_settings', 'jr_mt_settings_page' );
23
+ add_options_page( $jr_mt_plugin_data['Name'], 'Multiple Themes plugin', 'manage_options', 'jr_mt_settings', 'jr_mt_settings_page' );
24
+ }
25
+
26
+ /**
27
+ * Settings page for plugin
28
+ *
29
+ * Display and Process Settings page for this plugin.
30
+ *
31
+ */
32
+ function jr_mt_settings_page() {
33
+ global $jr_mt_plugin_data;
34
+ $jr_mt_plugin_data = array_merge( $jr_mt_plugin_data, jr_readme() );
35
+ global $jr_mt_themes_cache;
36
+ $jr_mt_themes_cache = wp_get_themes();
37
+ global $jr_mt_plugins_cache;
38
+ $jr_mt_plugins_cache = get_plugins();
39
+ add_thickbox();
40
+ echo '<div class="wrap">';
41
+ screen_icon( 'plugins' );
42
+ echo '<h2>' . $jr_mt_plugin_data['Name'] . '</h2>';
43
+
44
+ // Required because it is only called automatically for Admin Pages in the Settings section
45
+ settings_errors( 'jr_mt_settings' );
46
+
47
+ $theme = wp_get_theme()->Name;
48
+ global $jr_mt_options_cache;
49
+
50
+ $current_wp_version = get_bloginfo( 'version' );
51
+ if ( version_compare( $current_wp_version, '3.4', '<' ) ) {
52
+ // Plugin requires newer version of WordPress
53
+ echo '<h3>Error</h3><p>Here is the problem:<ul><li> &raquo; This Plugin (' . $jr_mt_plugin_data['Name']
54
+ . ') does not support versions of WordPress before WordPress Version '
55
+ . '3.4.0' . '.</li><li> &raquo; You are running WordPress Version ' . $current_wp_version
56
+ . '.</li><li> &raquo; This Plugin uses the wp_get_themes() function which became available in Version '
57
+ . '3.4.0 of WordPress.</li></ul></p>';
58
+ } else {
59
+ if ( $jr_mt_plugin_data['read readme'] && version_compare( $current_wp_version, $jr_mt_plugin_data['Tested up to'], '>' ) ) {
60
+ /* WordPress version is too new:
61
+ When currently-installed version of Plugin was installed,
62
+ it did not support currently-installed version of WordPress.
63
+ So, check if a newer version of plugin is available. */
64
+ $current = FALSE;
65
+ // Check if latest version of the plugin supports this version of WordPress
66
+ if ( !function_exists( 'plugins_api' ) ) {
67
+ require_once( ABSPATH . 'wp-admin/includes/plugin-install.php' );
68
+ }
69
+ $directory = plugins_api( 'plugin_information', array( 'slug' => $jr_mt_plugin_data['slug'],
70
+ 'fields' => array( 'download_link' => TRUE,
71
+ 'tested' => TRUE,
72
+ 'version' => TRUE,
73
+ 'error_data' => TRUE,
74
+ 'tags' => FALSE,
75
+ 'compatibility' => FALSE,
76
+ 'sections' => FALSE
77
+ )
78
+ ) );
79
+ if ( property_exists( $directory, 'errors' ) && ( $directory->error_data->plugins_api_failed == 'N;' ) ) {
80
+ // Plugin not found in WordPress Directory
81
+ echo '<h3>Warnings</h3><p>Here is the problem:<ul><li> &raquo; This Plugin (' . $jr_mt_plugin_data['Name']
82
+ . ') has not been tested with the version of WordPress you are currently running: ' . $current_wp_version
83
+ . '.</li><li> &raquo; This Plugin could not be found in the WordPress Plugin Directory. '
84
+ . 'If you are sure it should be there, the WordPress Plugin Directory may be currently unavailable or inaccessible from your web server.</li></ul></p>'
85
+ . '<p>The plugin will probably still work with your newer version of WordPress, but you need to be aware of the issue.</p>';
86
+ } else {
87
+ if ( version_compare( $current_wp_version, $directory->tested, '>' ) ) {
88
+ // Latest version of readme.txt for latest version of Plugin indicates that Plugin has not yet been tested for this version of WordPress
89
+ echo '<h3>Warning</h3><p>Here is the problem:<ul><li> &raquo; This Plugin (' . $jr_mt_plugin_data['Name']
90
+ . ') has not been tested with the version of WordPress you are currently running: ' . $current_wp_version
91
+ . '.</li></ul></p>'
92
+ . '<p>The plugin will probably still work with your newer version of WordPress, but you need to be aware of the issue.</p>';
93
+ } else {
94
+ if ( version_compare( $jr_mt_plugin_data['Version'], $directory->version, '=' ) ) {
95
+ /* The latest version of the Plugin has been installed,
96
+ but the readme.txt has been updated in the WordPress Plugin Directory
97
+ to indicate that it now supports the installed version of WordPress.
98
+
99
+ Latest version of Plugin has already been installed, but readme.txt is out of date,
100
+ so update readme.txt. */
101
+
102
+ $errmsg_before = '<h3>Warning</h3><p>Here is the problem:<ul><li> &raquo; This version (' . $jr_mt_plugin_data['Version']
103
+ . ') of this Plugin (' . $jr_mt_plugin_data['Name']
104
+ . ') has been tested with the version of WordPress you are currently running (' . $current_wp_version
105
+ . '), but</li><li> &raquo; The currently installed readme.txt file for this plugin is out of date,'
106
+ . '</li><li> &raquo; The attempt to update the readme.txt from the WordPress Plugin Repository failed, and'
107
+ . '</li><li> &raquo; The specific error is: ';
108
+ $errmsg_after = '</li></ul></p>'
109
+ . '<p>Another attempt will be made to update readme.txt each time this Settings page is displayed.'
110
+ . ' Nonetheless, this plugin should work properly even if readme.txt is out of date.</p>';
111
+
112
+ if ( is_wp_error( $file_name = download_url( $directory->download_link ) ) ) {
113
+ // Error
114
+ echo $errmsg_before . 'The plugin failed to completely download from the WordPress Repository with 300 seconds' . $errmsg_after;
115
+ } else {
116
+ if ( is_int( $resource_handle = zip_open( $file_name ) ) ) {
117
+ // Error
118
+ echo $errmsg_before
119
+ . "php function zip_open error number $resource_handle while attempting to open the plugin's"
120
+ . 'compressed .zip file successfully downloaded from the WordPress Plugin Repository'
121
+ . $errmsg_after;
122
+ } else {
123
+ $find_readme = TRUE;
124
+ while ( $find_readme && ( FALSE !== $dir_ent = zip_read( $resource_handle ) ) ) {
125
+ if ( is_int( $dir_ent ) ) {
126
+ // Error code
127
+ echo $errmsg_before
128
+ . "php function zip_read error number $dir_ent while attempting to read the plugin's"
129
+ . ' compressed .zip file successfully downloaded from the WordPress Plugin Repository'
130
+ . $errmsg_after;
131
+ // Get out of While loop
132
+ $find_readme = FALSE;
133
+ } else {
134
+ // Wait until the While loop gets to the readme.txt entry in the Plugin's Zip file
135
+ if ( zip_entry_name( $dir_ent ) == $jr_mt_plugin_data['slug'] . '/readme.txt' ) {
136
+ if ( FALSE === zip_entry_open( $resource_handle, $dir_ent, 'rb' ) ) {
137
+ // Error
138
+ echo $errmsg_before
139
+ . 'php function zip_entry_open failed to open readme.txt file compressed within plugin .zip file in WordPress Repository'
140
+ . $errmsg_after;
141
+ } else {
142
+ $filesize = zip_entry_filesize( $dir_ent );
143
+ if ( !is_int( $filesize ) || ( $filesize < 100 ) ) {
144
+ // Error
145
+ echo $errmsg_before
146
+ . 'Size, in bytes, of readme.txt file is being incorrectly reported by php function zip_entry_filesize as '
147
+ . var_export( $filesize, TRUE )
148
+ . $errmsg_after;
149
+ } else {
150
+ $readme_content = zip_entry_read( $dir_ent, $filesize );
151
+ if ( ( $readme_content === FALSE ) || ( $readme_content === '' ) ) {
152
+ // Error
153
+ echo $errmsg_before
154
+ . 'php function zip_entry_read failed to read readme.txt file compressed within plugin .zip file in WordPress Repository'
155
+ . $errmsg_after;
156
+ } else {
157
+ if ( FALSE === zip_entry_close( $dir_ent ) ) {
158
+ // Error
159
+ echo $errmsg_before
160
+ . 'php function zip_entry_close failed to close readme.txt file compressed within plugin .zip file in WordPress Repository'
161
+ . $errmsg_after;
162
+ } else {
163
+ // Alternate: file_put_contents( jr_mt_path() . 'readme.txt', $readme_content );
164
+ $write_return = jr_filesystem_text_write( $readme_content, 'readme.txt', jr_mt_path() );
165
+ if ( is_wp_error( $write_return ) || ( FALSE === $write_return ) ) {
166
+ // Error
167
+ echo $errmsg_before
168
+ . 'WP_filesystem failed to store readme.txt file as part of download/update process from WordPress Repository'
169
+ . $errmsg_after;
170
+ }
171
+ }
172
+ }
173
+ }
174
+ }
175
+ // Get out of While loop because we have found and processed readme.txt
176
+ $find_readme = FALSE;
177
+ }
178
+ }
179
+ }
180
+ zip_close( $resource_handle );
181
+ }
182
+ // Delete temporary download file
183
+ if ( !unlink( $file_name ) ) {
184
+ echo $errmsg_before
185
+ . "php unlink function failed to delete downloaded readme.txt in temporary download file $file_name"
186
+ . $errmsg_after;
187
+ }
188
+ }
189
+ $current = TRUE;
190
+ } else {
191
+ // Recommend updating Plugin to latest version which supports the version of WordPress being run,
192
+ // but the currently-installed version of the Plugin does not.
193
+ echo '<h3>Warning</h3><p>This plugin is out of date and should be updated for performance and reliability reasons.'
194
+ . ' Plugin updates are shown on the Plugins-Installed Plugins page and the Dashboard-Updates page here in the Admin panels.</p>';
195
+ }
196
+ }
197
+ }
198
+ } else {
199
+ // Currently-installed version of Plugin supports currently-installed version of WordPress
200
+ $current = TRUE;
201
+ }
202
+
203
+ global $jr_mt_plugins_cache;
204
+
205
+ $compatible = TRUE;
206
+
207
+ // Check for incompatible plugins that have been activated: BuddyPress and Theme Test Drive
208
+ global $jr_mt_incompat_plugins;
209
+ foreach ( $jr_mt_plugins_cache as $rel_path => $plugin_data ) {
210
+ if ( in_array( $plugin_data['Name'], $jr_mt_incompat_plugins ) && is_plugin_active( $rel_path ) ) {
211
+ if ( $compatible ) {
212
+ echo '<h3>Plugin Conflict Error Detected</h3>';
213
+ $compatible = FALSE;
214
+ }
215
+ echo '<p>This Plugin (' . $jr_mt_plugin_data['Name'] . ') cannot be used when the <b>' . $plugin_data['Name']
216
+ . '</b> plugin is Activated. If you wish to use the ' . $jr_mt_plugin_data['Name']
217
+ . ' plugin, please deactivate the ' . $plugin_data['Name']
218
+ . ' plugin (not just when using this Settings page, but whenever the '
219
+ . $jr_mt_plugin_data['Name'] . ' plugin is activated).</p>';
220
+ }
221
+ }
222
+
223
+ if ( $compatible ) {
224
+ ?>
225
+ <h3>Overview</h3>
226
+ <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.
227
+ You can choose from any of the <b>Available Themes</b> listed on the Appearance-Themes Admin panel for:
228
+ <ul>
229
+ <li> &raquo; All Pages</li>
230
+ <li> &raquo; All Posts</li>
231
+ <li> &raquo; Everything (see Advanced Settings below)</li>
232
+ <li> &raquo; The Site Home</li>
233
+ <li> &raquo; A Specific Page</li>
234
+ <li> &raquo; A Specific Post</li>
235
+ <li> &raquo; Any other non-Admin page that has its own Permalink; for example, a specific Archive or Category page</li>
236
+ </ul>
237
+ </p>
238
+ <h3>Important Notes</h3>
239
+ <?php
240
+ if ( function_exists('is_multisite') && is_multisite() ) {
241
+ 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.";
242
+ }
243
+ echo '<p>';
244
+ echo "The Current Theme, defined to WordPress in Appearance-Themes admin panel, is <b>$theme</b>.";
245
+ $settings = get_option( 'jr_mt_settings' );
246
+ if ( trim( $settings['current'] ) ) {
247
+ echo " But it is being overridden in Advanced Settings (see below), which set the plugin's default Theme to <b>";
248
+ echo wp_get_theme( $settings['current'] )->Name;
249
+ 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 Current Theme wherever you want it appear. Or, if you specify 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.';
250
+ } else {
251
+ 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 a different Theme for All Pages, All Posts or Everything, and wish to use the Current Theme for one or more specific Pages, Posts or other non-Admin pages.';
252
+ }
253
+ echo '</p>';
254
+ if ( $jr_mt_plugin_data['read readme'] ) {
255
+ if ( $current ) {
256
+ echo '<p>This Plugin (' . $jr_mt_plugin_data['Name'] . ') has been tested with the version of WordPress you are currently running: '
257
+ . $current_wp_version . '</p>';
258
+ }
259
+ } else {
260
+ echo '<p>Compatibility checks could not be done because the plugin was unable to read its readme.txt file, likely a user/permissions hosting issue.</p>';
261
+ }
262
+ if ( jr_mt_plugin_update_available() ) {
263
+ echo '<p>A new version of this Plugin (' . $jr_mt_plugin_data['Name'] . ') is available from the WordPress Repository.'
264
+ . ' We strongly recommend updating ASAP because new versions fix problems that users like yourself have reported to us.'
265
+ . ' <a class="thickbox" title="' . $jr_mt_plugin_data['Name'] . '" href="' . network_admin_url()
266
+ . 'plugin-install.php?tab=plugin-information&plugin=' . $jr_mt_plugin_data['slug']
267
+ . '&section=changelog&TB_iframe=true&width=640&height=768">Click here</a> for more details.</p>';
268
+ }
269
+ echo '<form action="options.php" method="POST">';
270
+
271
+ // Plugin Settings are displayed and entered here:
272
+ settings_fields( 'jr_mt_settings' );
273
+ do_settings_sections( 'jr_mt_settings_page' );
274
+ echo '<p><input name="save" type="submit" value="Save Changes" class="button-primary" /></p></form>';
275
+ }
276
+ }
277
+ echo '<hr /><h3>System Information</h3><p>You are currently running:<ul>';
278
+ echo "<li> &raquo; The {$jr_mt_plugin_data['Name']} plugin Version {$jr_mt_plugin_data['Version']}</li>";
279
+ echo "<li> &nbsp; &raquo;&raquo; The Path to the plugin's directory is " . rtrim( jr_mt_path(), '/' ) . '<li>';
280
+ echo "<li> &nbsp; &raquo;&raquo; The URL to the plugin's directory is " . plugins_url() . "/{$jr_mt_plugin_data['slug']}</li>";
281
+ echo "<li> &raquo; WordPress Version $current_wp_version</li>";
282
+ echo '<li> &nbsp; &raquo;&raquo; WordPress language is set to ' , get_bloginfo( 'language' ) . '</li>';
283
+ echo '<li> &raquo; ' . php_uname( 's' ) . ' operating system, Release/Version ' . php_uname( 'r' ) . ' / ' . php_uname( 'v' ) . '</li>';
284
+ echo '<li> &raquo; ' . php_uname( 'm' ) . ' computer hardware</li>';
285
+ echo '<li> &raquo; Host name ' . php_uname( 'n' ) . '</li>';
286
+ echo '<li> &raquo; php Version ' . phpversion() . '</li>';
287
+ echo '<li> &nbsp; &raquo;&raquo; php memory_limit ' . ini_get('memory_limit') . '</li>';
288
+ echo '<li> &raquo; Zend engine Version ' . zend_version() . '</li>';
289
+ echo '<li> &raquo; Web Server software is ' . getenv( 'SERVER_SOFTWARE' ) . '</li>';
290
+ if ( function_exists( 'apache_get_version' ) && ( FALSE !== $apache = apache_get_version() ) ) {
291
+ echo "<li> &nbsp; &raquo;&raquo; Apache Version $apache</li>";
292
+ }
293
+ global $wpdb;
294
+ echo '<li> &raquo; MySQL Version ' . $wpdb->get_var( 'SELECT VERSION();', 0, 0 ) . '</li>';
295
+
296
+ echo '</ul></p>';
297
+ }
298
+
299
+ add_action( 'admin_init', 'jr_mt_admin_init' );
300
+
301
+ /**
302
+ * Register and define the settings
303
+ *
304
+ * Everything to be stored and/or can be set by the user
305
+ *
306
+ */
307
+ function jr_mt_admin_init() {
308
+ register_setting( 'jr_mt_settings', 'jr_mt_settings', 'jr_mt_validate_settings' );
309
+ add_settings_section( 'jr_mt_all_settings_section',
310
+ 'For All Pages, All Posts and/or Site Home',
311
+ 'jr_mt_all_settings_expl',
312
+ 'jr_mt_settings_page'
313
+ );
314
+ $suffix = array(
315
+ 'Pages' => '<br />(Pages created with Add Page)',
316
+ 'Posts' => ''
317
+ );
318
+ foreach ( array( 'Pages', 'Posts' ) as $thing ) {
319
+ 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',
320
+ array( 'thing' => $thing ) );
321
+ }
322
+ add_settings_field( 'site_home',
323
+ 'Select Theme for Site Home<br />(' . get_home_url() . ')',
324
+ 'jr_mt_echo_site_home',
325
+ 'jr_mt_settings_page',
326
+ 'jr_mt_all_settings_section'
327
+ );
328
+ $settings = get_option( 'jr_mt_settings' );
329
+ $ids = $settings['ids'];
330
+ if ( !empty( $ids) ) {
331
+ add_settings_section( 'jr_mt_delete_settings_section',
332
+ 'To Display or Delete Theme Selections for Individual Pages or Posts',
333
+ 'jr_mt_delete_settings_expl',
334
+ 'jr_mt_settings_page'
335
+ );
336
+ add_settings_field( 'del_entry', 'Entries:', 'jr_mt_echo_delete_entry', 'jr_mt_settings_page', 'jr_mt_delete_settings_section' );
337
+ }
338
+ add_settings_section( 'jr_mt_single_settings_section',
339
+ 'For An Individual Page, Post or other non-Admin page;<br />or a group of pages, specified by URL Prefix',
340
+ 'jr_mt_single_settings_expl',
341
+ 'jr_mt_settings_page'
342
+ );
343
+ add_settings_field( 'add_theme', 'Theme', 'jr_mt_echo_add_theme', 'jr_mt_settings_page', 'jr_mt_single_settings_section' );
344
+ 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' );
345
+ 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' );
346
+ add_settings_section( 'jr_mt_advanced_settings_section',
347
+ 'Advanced Settings',
348
+ 'jr_mt_advanced_settings_expl',
349
+ 'jr_mt_settings_page'
350
+ );
351
+ add_settings_field( 'current',
352
+ 'Select Theme for Everything, to Override WordPress Current Theme (<b>' . wp_get_theme()->Name . '</b>)',
353
+ 'jr_mt_echo_current',
354
+ 'jr_mt_settings_page',
355
+ 'jr_mt_advanced_settings_section'
356
+ );
357
+ }
358
+
359
+ /**
360
+ * Section text for Section1
361
+ *
362
+ * Display an explanation of this Section
363
+ *
364
+ */
365
+ function jr_mt_all_settings_expl() {
366
+ ?>
367
+ <p>
368
+ In this section, you can select a different Theme for All Pages, All Posts and/or Site Home.
369
+ To remove a previously selected Theme, select the blank entry from the drop-down list.
370
+ </p>
371
+ <p>
372
+ 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
373
+ any other non-Admin pages that have their own Permalink; for example, specific Archive or Category pages.
374
+ Or groups of Pages, Posts or any other non-Admin pages that share the same URL Prefix.
375
+ </p>
376
+ <?php
377
+ }
378
+
379
+ function jr_mt_echo_all_things( $thing ) {
380
+ $settings = get_option( 'jr_mt_settings' );
381
+ $field = 'all_' . strtolower( $thing['thing'] );
382
+ jr_mt_themes_field( $field, $settings[$field], 'jr_mt_settings', TRUE );
383
+ }
384
+
385
+ function jr_mt_echo_site_home() {
386
+ $settings = get_option( 'jr_mt_settings' );
387
+ jr_mt_themes_field( 'site_home', $settings['site_home'], 'jr_mt_settings', FALSE );
388
+ }
389
+
390
+ /**
391
+ * Section text for Section2
392
+ *
393
+ * Display an explanation of this Section
394
+ *
395
+ */
396
+ function jr_mt_delete_settings_expl() {
397
+ ?>
398
+ <p>
399
+ In this section, all entries are displayed for Themes selected for individual Pages, Posts
400
+ and any other non-Admin pages that have their own Permalink; for example, specific Archive or Category pages.
401
+ Or groups of Pages, Posts or any other non-Admin pages that share the same URL Prefix.
402
+ </p>
403
+ <p>
404
+ You can delete any of these entries by filling in the check box beside each one.
405
+ To change the Theme for an entry, add the same entry with a different Theme in the section below this one.</p>
406
+ <?php
407
+ }
408
+
409
+ function jr_mt_echo_delete_entry() {
410
+ $entry_num = 0;
411
+ $settings = get_option( 'jr_mt_settings' );
412
+ foreach ( $settings['ids'] as $path_id => $opt_array ) {
413
+ ++$entry_num;
414
+ echo "Delete <input type='checkbox' id='del_entry' name='jr_mt_settings[del_entry][]' value='$path_id' /> &nbsp; Theme="
415
+ . wp_get_theme( $opt_array['theme'] )->Name . '; ';
416
+ if ( $path_id == '' ) {
417
+ echo 'Site=<a href="' . get_home_url() . '" target="_blank">Home</a>';
418
+ } else {
419
+ if ( $opt_array['type'] == 'prefix' ) {
420
+ echo 'Prefix=<a href="' . get_home_url() . "/$path_id" . '" target="_blank">' . "$path_id</a>";
421
+ } else {
422
+ if ( $opt_array['type'] == 'cat' ) {
423
+ echo 'Category=<a href="' . get_home_url() . '/?cat=' . $opt_array['id'] . '" target="_blank">' . get_cat_name( $opt_array['id'] ) . '</a>';
424
+ } else {
425
+ if ( $opt_array['type'] == 'archive' ) {
426
+ echo 'Archive=<a href="' . get_home_url() . '/?m=' . $opt_array['id'] . '" target="_blank">' . $opt_array['id'] . '</a>';
427
+ } else {
428
+ $p_array = get_posts( array( 'post_type' => 'any', 'include' => array( $path_id ) ) );
429
+ if ( empty( $p_array ) ) {
430
+ if ( $opt_array['type'] == 'admin' ) {
431
+ echo 'Admin=<a href="' . get_home_url() . '/' . $opt_array['rel_url'] . '" target="_blank">' . "$path_id</a>";
432
+ } else {
433
+ echo 'Path=<a href="' . get_home_url() . "/$path_id" . '" target="_blank">' . "$path_id</a>";
434
+ }
435
+ } else {
436
+ echo ucfirst( $p_array[0]->post_type ) . '=<a href="' . get_permalink( $path_id ) . '" target="_blank">' . $p_array[0]->post_title . '</a>';
437
+ }
438
+ }
439
+ }
440
+ }
441
+ }
442
+ echo '<br />';
443
+ }
444
+ }
445
+
446
+ /**
447
+ * Section text for Section3
448
+ *
449
+ * Display an explanation of this Section
450
+ *
451
+ */
452
+ function jr_mt_single_settings_expl() {
453
+ ?>
454
+ <p>
455
+ Select a Theme for an individual Page, Post or
456
+ any other non-Admin page that has its own Permalink; for example, a specific Archive or Category page.
457
+ Or for a group of pages which have URLs that all begin with the same characters ("Prefix").
458
+ </p>
459
+ <p>
460
+ Then cut and paste the URL of the desired Page, Post, Prefix or other non-Admin page.
461
+ And click the <b>Save Changes</b> button to add the entry.
462
+ </p>
463
+ <?php
464
+ }
465
+
466
+ function jr_mt_echo_add_theme() {
467
+ jr_mt_themes_field( 'add_theme', '', 'jr_mt_settings', FALSE );
468
+ }
469
+
470
+ function jr_mt_echo_add_path_id() {
471
+ ?>
472
+ <input id="add_path_id" name="jr_mt_settings[add_path_id]" type="text" size="100" maxlength="256" value="" />
473
+ <br />
474
+ (cut and paste URL here of Page, Post, Prefix or other)
475
+ <br />
476
+ URL must begin with
477
+ <?php
478
+ echo trim( get_home_url(), '\ /' ) . '/';
479
+ }
480
+
481
+ function jr_mt_echo_add_is_prefix() {
482
+ ?>
483
+ <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
484
+ <?php
485
+ }
486
+
487
+ /**
488
+ * Section text for Section4
489
+ *
490
+ * Display an explanation of this Section
491
+ *
492
+ */
493
+ function jr_mt_advanced_settings_expl() {
494
+ ?>
495
+ <p>
496
+ <b>Warning:</b>
497
+ As the name of the section implies, Advanced Settings
498
+ may surprise you with unintended consequences,
499
+ so please be careful.
500
+ </p>
501
+ <p>
502
+ <b>Theme for Everything</b> simplifies the use of a Theme with Admin panel settings that you need to change frequently,
503
+ when the Theme is only going to be used on one or more Pages or Posts.
504
+ The Theme can be set as the WordPress Current Theme through the Appearance-Themes admin panel,
505
+ and set for specific Pages or Posts using this plugin's settings (above),
506
+ with another Theme specified below as the plugin's default theme ("Theme for Everything").
507
+ </p>
508
+ <?php
509
+ }
510
+
511
+ function jr_mt_echo_current() {
512
+ $settings = get_option( 'jr_mt_settings' );
513
+ jr_mt_themes_field( 'current', $settings['current'], 'jr_mt_settings', TRUE );
514
+ echo '<br />(select blank entry for default: WordPress Current Theme defined in Appearance-Themes, currently <b>' . wp_get_theme()->Name . '</b>)';
515
+ }
516
+
517
+ function jr_mt_validate_settings( $input ) {
518
+ $valid = array();
519
+ foreach ( array( 'all_pages', 'all_posts', 'site_home', 'current' ) as $thing ) {
520
+ $valid[$thing] = $input[$thing];
521
+ }
522
+
523
+ $settings = get_option( 'jr_mt_settings' );
524
+ $ids = $settings['ids'];
525
+ if ( isset ( $input['del_entry'] ) ) {
526
+ foreach ( $input['del_entry'] as $del_entry ) {
527
+ unset( $ids[$del_entry] );
528
+ }
529
+ }
530
+
531
+ $url = rawurldecode( trim( $input['add_path_id'] ) );
532
+ if ( ( empty( $input['add_theme'] ) && !empty( $url ) ) || ( !empty( $input['add_theme'] ) && empty( $url ) ) ) {
533
+ add_settings_error(
534
+ 'jr_mt_settings',
535
+ 'jr_mt_emptyerror',
536
+ 'Both URL and Theme must be specified to add an Individual entry',
537
+ 'error'
538
+ );
539
+ } else {
540
+ if ( !empty( $url ) ) {
541
+ $validate_url = jr_mt_site_url( $url );
542
+ if ( $validate_url === TRUE ) {
543
+ extract( jr_mt_url_to_id( $url ) );
544
+ if ( isset ( $input['add_is_prefix'] ) && ( $input['add_is_prefix'] == "true" ) ) {
545
+ if ( parse_url( $url, PHP_URL_QUERY ) === NULL ) {
546
+ $ids[$rel_url] = array(
547
+ 'theme' => $input['add_theme'],
548
+ 'type' => 'prefix',
549
+ 'id' => $id,
550
+ 'page_url' => $page_url,
551
+ 'rel_url' => $rel_url,
552
+ 'url' => $url
553
+ );
554
+ } else {
555
+ add_settings_error(
556
+ 'jr_mt_settings',
557
+ 'jr_mt_queryerror',
558
+ '?key=val&key=val Queries are not supported in a URL Prefix',
559
+ 'error'
560
+ );
561
+
562
+ }
563
+ } else {
564
+ if ( $home ) {
565
+ add_settings_error(
566
+ 'jr_mt_settings',
567
+ 'jr_mt_homeerror',
568
+ 'Please use "Select Theme for Site Home" field instead of specifying Site Home URL as an individual entry.',
569
+ 'error'
570
+ );
571
+ } else {
572
+ if ( $type == 'admin' ) {
573
+ add_settings_error(
574
+ 'jr_mt_settings',
575
+ 'jr_mt_adminerror',
576
+ 'Admin Page URLs are not allowed because no known Themes alter the appearance of Admin pages.',
577
+ 'error'
578
+ );
579
+ } else {
580
+ if ( $id === FALSE ) {
581
+ $key = $page_url;
582
+ } else {
583
+ $key = $id;
584
+ }
585
+ $ids[$key] = array(
586
+ 'theme' => $input['add_theme'],
587
+ 'type' => $type,
588
+ 'id' => $id,
589
+ 'page_url' => $page_url,
590
+ 'rel_url' => $rel_url,
591
+ 'url' => $url
592
+ );
593
+ }
594
+ }
595
+ }
596
+ } else {
597
+ add_settings_error(
598
+ 'jr_mt_settings',
599
+ 'jr_mt_urlerror',
600
+ "Invalid URL specified for Individual page/post: '$url'. $validate_url",
601
+ 'error'
602
+ );
603
+ }
604
+ }
605
+ }
606
+ $errors = get_settings_errors();
607
+ if ( empty( $errors ) ) {
608
+ add_settings_error(
609
+ 'jr_mt_settings',
610
+ 'jr_mt_saved',
611
+ 'Settings Saved',
612
+ 'updated'
613
+ );
614
+ }
615
+ $valid['ids'] = $ids;
616
+ return $valid;
617
+ }
618
+
619
+ // $theme_name is the name of the Theme's folder within the Theme directory
620
+ function jr_mt_themes_field( $field_name, $theme_name, $setting, $excl_current_theme ) {
621
+ echo "<select id='$field_name' name='$setting" . "[$field_name]' size='1'>";
622
+ if ( empty( $theme_name ) ) {
623
+ $selected = 'selected="selected"';
624
+ } else {
625
+ $selected = '';
626
+ }
627
+ echo "<option value='' $selected></option>";
628
+ global $jr_mt_themes_cache;
629
+ foreach ( $jr_mt_themes_cache as $folder => $theme_obj ) {
630
+ if ( $excl_current_theme ) {
631
+ if ( ( jr_mt_current_theme( 'stylesheet' ) == $theme_obj['stylesheet'] ) && ( jr_mt_current_theme( 'template' ) == $theme_obj['template'] ) ) {
632
+ // Skip the Current Theme
633
+ continue;
634
+ }
635
+ }
636
+ if ( $theme_name == $folder ) {
637
+ $selected = 'selected="selected"';
638
+ } else {
639
+ $selected = '';
640
+ }
641
+ $name = $theme_obj->Name;
642
+ echo "<option value='$folder' $selected>$name</option>";
643
+ }
644
+ echo '</select>' . PHP_EOL;
645
+ }
646
+
647
+ ?>
includes/debug/debug.php ADDED
@@ -0,0 +1,40 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ // Exit if .php file accessed directly
3
+ if ( !defined( 'ABSPATH' ) ) exit;
4
+
5
+
6
+ /* require_once( jr_mt_path() . 'includes/debug/debug.php' );
7
+ jr_dump( 'jr_mt_validate_settings $input', $input );
8
+ */
9
+
10
+ function jr_dump( $comment, $dump_var ) {
11
+ $file_name = 'jonradio-dump.txt';
12
+
13
+ $header = '***' . current_time('mysql') . ': ' . $_SERVER['SERVER_NAME'] . $_SERVER['REQUEST_URI'];
14
+ ob_start();;
15
+ echo "$comment: ";
16
+ var_dump( $dump_var );
17
+ $output = ob_get_clean() . jr_dump_env();
18
+ if ( function_exists('is_multisite') && is_multisite() ) {
19
+ global $site_id, $blog_id;
20
+ $file_name = $site_id . '-' . $blog_id . '-' . $file_name;
21
+ }
22
+ $file = fopen( plugin_dir_path( __FILE__ ) . $file_name, 'at' );
23
+ fwrite( $file, $header . PHP_EOL . $output );
24
+ fclose( $file );
25
+
26
+ return;
27
+ }
28
+
29
+ function jr_dump_env() {
30
+ global $jr_dump_env_first;
31
+ if ( isset( $jr_dump_env_first ) ) {
32
+ $output = '';
33
+ } else {
34
+ $jr_dump_env_first = FALSE;
35
+ $output = PHP_EOL;
36
+
37
+ }
38
+ return $output;
39
+ }
40
+ ?>
includes/debug/index.html ADDED
File without changes
includes/functions.php ADDED
@@ -0,0 +1,357 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ // Exit if .php file accessed directly
3
+ if ( !defined( 'ABSPATH' ) ) exit;
4
+
5
+
6
+ /**
7
+ * Return WordPress Current Theme, as defined in Appearance Admin panels
8
+ *
9
+ * Obtains Folder Name of Current Theme, from 'template' option of wp_load_alloptions().
10
+ *
11
+ * @param string $option parameter to select current template or stylesheet
12
+ * @return string type Folder Name of Current Theme
13
+ */
14
+ function jr_mt_current_theme( $option ) {
15
+ global $jr_mt_options_cache;
16
+ return $jr_mt_options_cache[$option];
17
+ }
18
+
19
+ /**
20
+ * Given URL, return post or page ID, if possible, and relative path if not
21
+ *
22
+ * Calls jr_mt_query_keywords.
23
+ *
24
+ * @param string $url full URL of WordPress page, post, admin, etc.
25
+ * @return array array with keys of "type", "id" and "page_url":
26
+ * string type "pages", "posts" or "admin"
27
+ * string id Page ID or Post ID or FALSE
28
+ * string page_url relative URL WordPress page, post, admin, etc. or FALSE
29
+ * string rel_url URL relative to WordPress home
30
+ * bool home is URL Site Home?
31
+ */
32
+ function jr_mt_url_to_id( $url_orig ) {
33
+ // Some hosts, likely only IIS, insert an erroneous "/index.php" into the middle of the Permalink in $_SERVER['REQUEST_URI']
34
+ $url = str_replace( '/index.php', '', $url_orig );
35
+
36
+ $trim = '\ /'; // remove leading and trailing backslashes, blanks and forward slashes
37
+
38
+ $is_home = FALSE;
39
+
40
+ // get_home_url() returns "https://subdomain.domain.com/wp" - the full URL of the home page of the site
41
+ $home = trim( parse_url( get_home_url(), PHP_URL_PATH ), $trim ); // "wp"
42
+
43
+ $admin_home = trim( parse_url( admin_url(), PHP_URL_PATH ), $trim );
44
+ $page_url = trim( parse_url( $url, PHP_URL_PATH ), $trim ); // "wp/fruit/apples"
45
+ $is_admin = ( $admin_home == substr( $page_url, 0, strlen( $admin_home ) ) );
46
+ if ( !empty( $home ) ) { // Only if WordPress is installed in a subfolder, NOT in the Root
47
+ $page_url = trim( substr( $page_url, stripos( $page_url, $home ) + strlen( $home ) ), $trim ); // "fruit/apples"
48
+ }
49
+ $rel_url = $page_url;
50
+
51
+ $type = FALSE;
52
+
53
+ $id = jr_mt_query_keywords( parse_url( $url, PHP_URL_QUERY ) );
54
+ if ( $id === NULL ) {
55
+ if ( $is_admin ) {
56
+ $id = FALSE;
57
+ $type = 'admin';
58
+ } else {
59
+ // Check for home page (url_to_postid() does not work for home page)
60
+ if ( empty( $page_url ) ) {
61
+ $is_home = TRUE;
62
+ $id = get_option('page_on_front');
63
+ if ( $id == 0 ) {
64
+ // There is no home Page; posts are displayed instead on the home page
65
+ $page_url = '';
66
+ $id = FALSE;
67
+ } else {
68
+ $type = 'pages';
69
+ }
70
+ } else {
71
+ global $wp_rewrite;
72
+ if ( is_null( $wp_rewrite ) ) {
73
+ $GLOBALS['wp_rewrite'] = new WP_Rewrite();
74
+ }
75
+ global $wp;
76
+ if ( is_null( $wp ) ) {
77
+ $GLOBALS['jr_mt_cache'] = FALSE;
78
+ $wp = (object) array( 'public_query_vars' => array() );
79
+ } else {
80
+ if ( !isset( $wp->public_query_vars ) ) {
81
+ $GLOBALS['jr_mt_cache'] = FALSE;
82
+ $wp->public_query_vars = array();
83
+ }
84
+ }
85
+ $id = url_to_postid( $url );
86
+ if ( $id == 0 ) {
87
+ $id = FALSE;
88
+ } else {
89
+ $post_obj = get_post( $id );
90
+ if ( $post_obj->post_type == 'page' ) {
91
+ $type = 'pages';
92
+ } else {
93
+ if ( $post_obj->post_type == 'post' ) {
94
+ $type = 'posts';
95
+ }
96
+ }
97
+ }
98
+ }
99
+ }
100
+ } else {
101
+ // id in query of URL (?keyword=value&keyword=value)
102
+ $type = key( $id );
103
+ $id = $id[$type];
104
+ $page_url = FALSE;
105
+ }
106
+ return array(
107
+ 'type' => $type,
108
+ 'id' => $id,
109
+ 'page_url' => $page_url,
110
+ 'rel_url' => $rel_url,
111
+ 'home' => $is_home
112
+ );
113
+ }
114
+
115
+ /**
116
+ * Return page_id= or p= (post ID) or page= (admin page) value from a URL
117
+ *
118
+ * Calls parse_str function in its own variable space because it could create virtually any variable name!
119
+ * Only looks at page_id=, p= and page= now, but could be expanded to other query keywords.
120
+ *
121
+ * @param string $url_query Query portion (after the ?) in a URL
122
+ * @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
123
+ */
124
+ function jr_mt_query_keywords( $url_query ) {
125
+ if ( $url_query === NULL ) {
126
+ return NULL;
127
+ } else {
128
+ parse_str( $url_query );
129
+ if ( isset( $page_id ) ) {
130
+ return array( 'pages' => $page_id );
131
+ } else {
132
+ if ( isset( $p ) ) {
133
+ return array( 'posts' => $p );
134
+ } else {
135
+ if ( isset( $page ) ) {
136
+ return array( 'admin' => $page );
137
+ } else {
138
+ if ( isset( $cat ) ) {
139
+ return array( 'cat' => $cat );
140
+ } else {
141
+ if ( isset( $m ) ) {
142
+ return array( 'archive' => $m );
143
+ } else {
144
+ if ( isset( $s ) ) {
145
+ return array( 'livesearch' => $s );
146
+ } else {
147
+ return NULL;
148
+ }
149
+ }
150
+ }
151
+ }
152
+ }
153
+ }
154
+ }
155
+ }
156
+
157
+ /**
158
+ * Is the URL on the current WordPress web site?
159
+ *
160
+ * Checks if URL begins with Site Home URL.
161
+ *
162
+ * @param string $url URL to be checked to be sure it is "on" the current WordPress web site
163
+ * @return var bool TRUE if URL on current WordPress web site; string error message otherwise
164
+ */
165
+ function jr_mt_site_url( $url ) {
166
+ $check_url = trim( $url );
167
+ if ( strcasecmp( 'http', substr( $check_url, 0, 4 ) ) != 0 ) {
168
+ return 'URL does not begin with http://';
169
+ }
170
+ $site_home = get_home_url();
171
+ if ( strcasecmp( $site_home, substr( $check_url, 0, strlen( $site_home ) ) ) != 0 ) {
172
+ return "URL specified is not part of current WordPress web site. URL must begin with '$site_home'";
173
+ }
174
+ return TRUE;
175
+ }
176
+
177
+ function jr_readme() {
178
+ $readme = array( 'read readme' => FALSE );
179
+ $file_array = jr_filesystem_text_read('readme.txt', jr_mt_path());
180
+ if ( ( FALSE !== $file_array ) && !is_wp_error( $file_array ) ) {
181
+ // Get first non-blank line
182
+ $results = jr_nextline( $file_array, 0 );
183
+ if ( '===' === substr( $results['line'], 0, 3) ) {
184
+ $readme['read readme'] = TRUE;
185
+ $readme['name'] = trim( $results['line'], ' =' );
186
+ do {
187
+ $results = jr_nextline( $file_array, $results['index'] );
188
+ if ( '==' === substr( $results['line'], 0, 2) ) {
189
+ break;
190
+ } else {
191
+ $colon = strpos( $results['line'], ":", 4 );
192
+ if ( $colon !== FALSE ) {
193
+ $key = preg_replace( '/\s+/', ' ', trim( substr( $results['line'], 0, $colon ) ) );
194
+ $readme[$key] = trim( substr( $results['line'], $colon + 1 ) );
195
+ }
196
+ }
197
+ } while ( $results['line'] != "" );
198
+ }
199
+ }
200
+ return $readme;
201
+ }
202
+ function jr_nextline( $file_array, $index ) {
203
+ $line = "";
204
+ while ( ( $index < count( $file_array ) ) && ( $line === "" ) ) {
205
+ $line = trim( $file_array[$index++] );
206
+ };
207
+ return array( 'line' => $line, 'index' => $index );
208
+ // ['line'] of "" indicates End of File
209
+ // ['index'] is the next line to be read
210
+ }
211
+
212
+ /**
213
+ * Initialize Filesystem object
214
+ *
215
+ * @param str $form_url - URL of the page to display request form
216
+ * @param str $method - connection method
217
+ * @param str $context - destination folder
218
+ * @param array $fields - fileds of $_POST array that should be preserved between screens
219
+ * @return bool/str - false on failure, stored text on success
220
+ **/
221
+ function jr_filesystem_init( $form_url, $method, $context, $fields = null ) {
222
+ global $wp_filesystem;
223
+
224
+ /* first attempt to get credentials */
225
+ if (false === ($creds = request_filesystem_credentials($form_url, $method, false, $context, $fields))) {
226
+
227
+ /**
228
+ * if we comes here - we don't have credentials
229
+ * so the request for them is displaying
230
+ * no need for further processing
231
+ **/
232
+ return false;
233
+ }
234
+
235
+ /* now we got some credentials - try to use them*/
236
+ if ( !WP_Filesystem( $creds ) ) {
237
+
238
+ /* incorrect connection data - ask for credentials again, now with error message */
239
+ request_filesystem_credentials($form_url, $method, true, $context);
240
+ return false;
241
+ }
242
+
243
+ return true; //filesystem object successfully initiated
244
+ }
245
+
246
+ /**
247
+ * Read text from file
248
+ *
249
+ * @param str $form_url - URL of the page where request form will be displayed
250
+ * @return bool/str - false on failure, stored text on success
251
+ **/
252
+ function jr_filesystem_text_read($file_name, $context){
253
+ global $wp_filesystem;
254
+
255
+ $text = '';
256
+
257
+ $form_url = wp_nonce_url('themes.php?page=jr_mt_settings', 'filesystem_dummy_screen');
258
+ $method = ''; //leave this empty to perform test for 'direct' writing
259
+
260
+ if(!jr_filesystem_init($form_url, $method, $context))
261
+ return false; //stop further processing when request forms displaying
262
+
263
+ /*
264
+ * now $wp_filesystem could be used
265
+ * get correct target file first
266
+ **/
267
+ $target_dir = $wp_filesystem->find_folder($context);
268
+ $target_file = trailingslashit($target_dir).$file_name;
269
+
270
+ /* read the file */
271
+ if($wp_filesystem->exists($target_file)){ //check for existence
272
+
273
+ $text = $wp_filesystem->get_contents_array($target_file);
274
+ if(!$text)
275
+ return new WP_Error('reading_error', 'Error when reading file'); //return error object
276
+
277
+ }
278
+
279
+ return $text;
280
+ }
281
+
282
+ /**
283
+ * Perform writing into file
284
+ *
285
+ * @param str $form_url - URL of the page to display request form
286
+ * @return bool/str - false on failure, stored text on success
287
+ **/
288
+ function jr_filesystem_text_write( $content, $file_name, $context ) {
289
+ global $wp_filesystem;
290
+
291
+ $method = ''; //leave this empty to perform test for 'direct' writing
292
+ $form_url = wp_nonce_url('themes.php?page=jr_mt_settings', 'filesystem_dummy_screen');
293
+
294
+ if(!jr_filesystem_init($form_url, $method, $context))
295
+ return false; //stop further processing when request form is displaying
296
+
297
+ /*
298
+ * now $wp_filesystem could be used
299
+ * get correct target file first
300
+ **/
301
+ $target_dir = $wp_filesystem->find_folder($context);
302
+ $target_file = trailingslashit($target_dir) . $file_name;
303
+
304
+ /* write into file */
305
+ if(!$wp_filesystem->put_contents($target_file, $content, FS_CHMOD_FILE))
306
+ return new WP_Error('writing_error', 'Error when writing file'); //return error object
307
+
308
+ return $content;
309
+ }
310
+
311
+ /**
312
+ * Update available for Plugin?
313
+ *
314
+ * @return bool - TRUE if an update is available in the WordPress Repository,
315
+ * FALSE if no update is available or if the update_plugins transient is not available
316
+ * (which also results in an error message).
317
+ **/
318
+ function jr_mt_plugin_update_available() {
319
+ global $jr_mt_update_plugins;
320
+ if ( !isset( $jr_mt_update_plugins ) ) {
321
+ $transient = get_site_transient( 'update_plugins' );
322
+ if ( FALSE === $transient ) {
323
+ // Error
324
+ return FALSE;
325
+ } else {
326
+ $jr_mt_update_plugins = $transient;
327
+ }
328
+ }
329
+ if ( empty( $jr_mt_update_plugins->response ) ) {
330
+ return FALSE;
331
+ }
332
+ return array_key_exists( jr_mt_plugin_basename(), $jr_mt_update_plugins->response );
333
+ }
334
+
335
+ /**
336
+ * What Themes are defined to Plugin?
337
+ *
338
+ * @return arr - a list of Themes (folder names) defined in Settings of Plugin
339
+ **/
340
+ function jr_mt_themes_defined() {
341
+ $themes = array();
342
+ $settings = get_option( 'jr_mt_settings' );
343
+ foreach ( $settings as $key => $value ) {
344
+ if ( 'ids' == $key ) {
345
+ foreach ( $value as $id => $arr ) {
346
+ $themes[] = $arr['theme'];
347
+ }
348
+ } else {
349
+ if ( !empty( $value ) ) {
350
+ $themes[] = $value;
351
+ }
352
+ }
353
+ }
354
+ return array_unique( $themes );
355
+ }
356
+
357
+ ?>
includes/index.html ADDED
File without changes
includes/select-theme.php ADDED
@@ -0,0 +1,153 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ // Exit if .php file accessed directly
3
+ if ( !defined( 'ABSPATH' ) ) exit;
4
+
5
+
6
+ // Select the relevant Theme
7
+
8
+ add_filter( 'pre_option_stylesheet', 'jr_mt_stylesheet' );
9
+ add_filter( 'pre_option_template', 'jr_mt_template' );
10
+
11
+ function jr_mt_stylesheet() {
12
+ return jr_mt_theme( 'stylesheet' );
13
+ }
14
+
15
+ function jr_mt_template() {
16
+ return jr_mt_theme( 'template' );
17
+ }
18
+
19
+ function jr_mt_theme( $option ) {
20
+ /* The hooks that (indirectly) call this function are called repeatedly by WordPress,
21
+ so do the checking once and store the values in a global array.
22
+ $jt_mt_theme['stylesheet'] - Stylesheet Name of Theme chosen
23
+ $jt_mt_theme['template'] - Template Name of Theme chosen
24
+
25
+ Very important note:
26
+ - get_option( 'jr_mt_settings' ) ['ids']['theme'] is the Theme Subdirectory Name,
27
+ as opposed to the Template or Stylesheet Name for the Theme.
28
+ - likewise, the variable local variable $theme
29
+ These three different values for each Theme must be clearly separated, as all three usually
30
+ match, but do not have to, e.g. - Child Themes.
31
+ */
32
+ $GLOBALS['jr_mt_cache'] = TRUE;
33
+ global $jr_mt_theme;
34
+ if ( !isset( $jr_mt_theme ) ) {
35
+ $jr_mt_theme = array();
36
+ }
37
+ if ( !isset( $jr_mt_theme[$option] ) ) {
38
+ $theme = jr_mt_chosen();
39
+ if ( $theme === FALSE ) {
40
+ // Get both at once, to save a repeat of this logic later:
41
+ $jr_mt_theme['stylesheet'] = jr_mt_current_theme( 'stylesheet' );
42
+ $jr_mt_theme['template'] = jr_mt_current_theme( 'template' );
43
+ } else {
44
+ $themes = wp_get_themes();
45
+ $jr_mt_theme['stylesheet'] = $themes[$theme]->stylesheet;
46
+ $jr_mt_theme['template'] = $themes[$theme]->template;
47
+ }
48
+ }
49
+ $theme = $jr_mt_theme[$option];
50
+ global $jr_mt_cache;
51
+ if ( $jr_mt_cache === FALSE ) {
52
+ unset( $jr_mt_theme[$option] );
53
+ }
54
+ return $theme;
55
+ }
56
+
57
+ // Returns FALSE for Current Theme
58
+ function jr_mt_chosen() {
59
+ if ( is_admin() ) {
60
+ // Admin panel
61
+ // return P2 theme if p2ajax= is present; current theme otherwise
62
+ parse_str( $_SERVER['QUERY_STRING'], $keywords );
63
+ if ( isset( $keywords['p2ajax'] ) && array_key_exists( 'p2', wp_get_themes() ) ) {
64
+ $theme = 'p2';
65
+ } else {
66
+ $theme = FALSE; // Current Theme
67
+ }
68
+ } else {
69
+ // Non-Admin page, i.e. - Public Site, etc.
70
+ extract( jr_mt_url_to_id( rawurldecode( 'http://' . $_SERVER['SERVER_NAME'] . $_SERVER['REQUEST_URI'] ) ) );
71
+ if ( ( 'livesearch' === $type ) && ( FALSE !== $livesearch_theme = jr_mt_livesearch_theme() ) ) {
72
+ return $livesearch_theme;
73
+ }
74
+ $settings = get_option( 'jr_mt_settings' );
75
+ if ( $home ) {
76
+ if ( trim( $settings['site_home'] ) != '' ) {
77
+ return $settings['site_home'];
78
+ }
79
+ }
80
+ $ids = $settings['ids'];
81
+ if ( $id === FALSE ) {
82
+ if ( isset( $ids[$page_url] ) ) {
83
+ $theme = $ids[$page_url]['theme'];
84
+ } else {
85
+ $theme = jr_mt_check_all( $type, $rel_url, $ids );
86
+ }
87
+ } else {
88
+ if ( isset( $ids[$id] ) ) {
89
+ $theme = $ids[$id]['theme'];
90
+ } else {
91
+ $theme = jr_mt_check_all( $type, $rel_url, $ids );
92
+ }
93
+ }
94
+ }
95
+ return $theme;
96
+ }
97
+
98
+ // Returns FALSE for Current Theme
99
+ function jr_mt_check_all( $type, $rel_url, $ids ) {
100
+ // Check Prefix entries first, because we already know there is no specific entry for this URL.
101
+ $theme = '';
102
+ $match_length = 0;
103
+ foreach ( $ids as $key => $array ) {
104
+ if ( $array['type'] == 'prefix' ) {
105
+ $this_length = strlen( $array['rel_url'] );
106
+ if ( $array['rel_url'] == substr( $rel_url, 0, $this_length ) ) {
107
+ // Need to find longest match if there are multiple prefix matches.
108
+ if ( $this_length > $match_length ) {
109
+ $theme = $array['theme'];
110
+ $match_length = $this_length;
111
+ }
112
+ }
113
+ }
114
+ }
115
+ // See if a Prefix entry was found
116
+ if ( $match_length == 0 ) {
117
+ if ( $type === FALSE ) {
118
+ $theme = FALSE; // Current Theme
119
+ } else {
120
+ $settings = get_option( 'jr_mt_settings' );
121
+ if ( isset( $settings["all_$type"] ) ) {
122
+ $theme = $settings["all_$type"];
123
+ } else {
124
+ $theme = '';
125
+ }
126
+ if ( empty( $theme ) ) {
127
+ $theme = FALSE; // Current Theme
128
+ }
129
+ }
130
+ }
131
+ return $theme;
132
+ }
133
+
134
+ function jr_mt_livesearch_theme() {
135
+ $livesearch_themes = array( 'knowhow' );
136
+ if ( in_array( jr_mt_current_theme( 'stylesheet' ), $livesearch_themes ) ) {
137
+ return jr_mt_current_theme( 'stylesheet' );
138
+ } else {
139
+ if ( in_array( jr_mt_current_theme( 'template' ), $livesearch_themes ) ) {
140
+ return jr_mt_current_theme( 'template' );
141
+ } else {
142
+ // Go through all the Themes defined in the Plugin's settings
143
+ foreach ( jr_mt_themes_defined() as $theme ) {
144
+ if ( in_array( $theme, $livesearch_themes ) ) {
145
+ return $theme;
146
+ }
147
+ }
148
+ }
149
+ }
150
+ return FALSE;
151
+ }
152
+
153
+ ?>
index.html ADDED
File without changes
jonradio-multiple-themes.php ADDED
@@ -0,0 +1,228 @@