Completed
Push — master ( 2a3d9e...0c2493 )
by Andrey
01:58
created

toolbar-theme-switcher.php (19 issues)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
0 ignored issues
show
Coding Style Compatibility introduced by
For compatibility and reusability of your code, PSR1 recommends that a file should introduce either new symbols (like classes, functions, etc.) or have side-effects (like outputting something, or including other files), but not both at the same time. The first symbol is defined on line 37 and the first side effect is on line 32.

The PSR-1: Basic Coding Standard recommends that a file should either introduce new symbols, that is classes, functions, constants or similar, or have side effects. Side effects are anything that executes logic, like for example printing output, changing ini settings or writing to a file.

The idea behind this recommendation is that merely auto-loading a class should not change the state of an application. It also promotes a cleaner style of programming and makes your code less prone to errors, because the logic is not spread out all over the place.

To learn more about the PSR-1, please see the PHP-FIG site on the PSR-1.

Loading history...
2
/*
3
Plugin Name: Toolbar Theme Switcher
4
Plugin URI: https://github.com/Rarst/toolbar-theme-switcher
5
Description: Adds toolbar menu that allows users to switch theme for themselves.
6
Author: Andrey "Rarst" Savchenko
7
Version: 1.4
8
Author URI: http://www.rarst.net/
9
Text Domain: toolbar-theme-switcher
10
Domain Path: /lang
11
License: MIT
12
13
Copyright (c) 2012 Andrey Savchenko
14
15
Permission is hereby granted, free of charge, to any person obtaining a copy of this
16
software and associated documentation files (the "Software"), to deal in the Software
17
without restriction, including without limitation the rights to use, copy, modify, merge,
18
publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
19
to whom the Software is furnished to do so, subject to the following conditions:
20
21
The above copyright notice and this permission notice shall be included in all copies
22
or substantial portions of the Software.
23
24
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
25
INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
26
PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
27
FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
28
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
29
DEALINGS IN THE SOFTWARE.
30
*/
31
32
Toolbar_Theme_Switcher::on_load();
33
34
/**
35
 * Main plugin class.
36
 */
37
class Toolbar_Theme_Switcher {
0 ignored issues
show
Coding Style Compatibility introduced by
PSR1 recommends that each class must be in a namespace of at least one level to avoid collisions.

You can fix this by adding a namespace to your class:

namespace YourVendor;

class YourClass { }

When choosing a vendor namespace, try to pick something that is not too generic to avoid conflicts with other libraries.

Loading history...
38
39
	/** @var WP_Theme $theme */
40
	public static $theme = false;
41
42
	/**
43
	 * Hooks that need to be set up early.
44
	 */
45
	static function on_load() {
0 ignored issues
show
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
46
47
		add_action( 'setup_theme', array( __CLASS__, 'setup_theme' ) );
48
		add_action( 'init', array( __CLASS__, 'init' ) );
49
	}
50
51
	/**
52
	 * Loads cookie and sets up theme filters.
53
	 */
54
	static function setup_theme() {
0 ignored issues
show
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
55
56
		global $pagenow;
57
58
		if ( ( is_admin() && 'themes.php' == $pagenow ) || ! self::can_switch_themes() ) {
59
			return;
60
		}
61
62
		if ( isset( $_GET['tts_reset'] ) ) {
63
			setcookie( self::get_cookie_name(), '', 1 );
64
			nocache_headers();
65
			wp_safe_redirect( home_url() );
66
			die;
0 ignored issues
show
Coding Style Compatibility introduced by
The method setup_theme() contains an exit expression.

An exit expression should only be used in rare cases. For example, if you write a short command line script.

In most cases however, using an exit expression makes the code untestable and often causes incompatibilities with other libraries. Thus, unless you are absolutely sure it is required here, we recommend to refactor your code to avoid its usage.

Loading history...
67
		}
68
69
		self::load_cookie();
70
71
		if ( empty( self::$theme ) ) {
72
			return;
73
		}
74
75
		add_filter( 'pre_option_template', array( self::$theme, 'get_template' ) );
76
		add_filter( 'pre_option_stylesheet', array( self::$theme, 'get_stylesheet' ) );
77
		add_filter( 'pre_option_stylesheet_root', array( self::$theme, 'get_theme_root' ) );
78
		$parent = self::$theme->parent();
79
		add_filter( 'pre_option_template_root', array( empty( $parent ) ? self::$theme : $parent, 'get_theme_root' ) );
80
		add_filter( 'pre_option_current_theme', '__return_false' );
81
	}
82
83
	/**
84
	 * If allowed to switch theme.
85
	 *
86
	 * @return boolean
87
	 */
88
	static function can_switch_themes() {
0 ignored issues
show
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
89
90
		$capability = apply_filters( 'tts_capability', 'switch_themes' );
91
92
		return apply_filters( 'tts_can_switch_themes', current_user_can( $capability ) );
93
	}
94
95
	/**
96
	 * Sets if cookie is defined to non-default theme.
97
	 */
98
	static function load_cookie() {
0 ignored issues
show
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
99
100
		$cookie_name = self::get_cookie_name();
101
102
		if ( empty( $_COOKIE[ $cookie_name ] ) ) {
103
			return;
104
		}
105
106
		$theme = wp_get_theme( $_COOKIE[ $cookie_name ] );
107
108
		if (
109
			$theme->exists()
110
			&& $theme->get( 'Name' ) != get_option( 'current_theme' )
111
			&& $theme->is_allowed()
112
		) {
113
			self::$theme = $theme;
114
		}
115
	}
116
117
	/**
118
	 * Returns cookie name, based on home URL so it differs for sites in multisite.
119
	 *
120
	 * @return string
121
	 */
122
	static function get_cookie_name() {
0 ignored issues
show
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
123
124
		static $hash;
125
126
		if ( empty( $hash ) ) {
127
			$hash = 'wordpress_tts_theme_' . md5( home_url( '', 'http' ) );
128
		}
129
130
		return $hash;
131
	}
132
133
	/**
134
	 * If theme is in list of allowed to be switched to.
135
	 *
136
	 * @deprecated
137
	 *
138
	 * @param WP_Theme $theme
139
	 *
140
	 * @return bool
141
	 */
142
	static function is_allowed( $theme ) {
0 ignored issues
show
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
143
144
		return array_key_exists( $theme->get( 'Name' ), self::get_allowed_themes() );
145
	}
146
147
	/**
148
	 * Template slug filter.
149
	 *
150
	 * @param string $template
151
	 *
152
	 * @deprecated
153
	 *
154
	 * @return string
155
	 */
156
	static function template( $template ) {
0 ignored issues
show
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
157
158
		return self::get_theme_field( 'Template', $template );
0 ignored issues
show
Deprecated Code introduced by
The method Toolbar_Theme_Switcher::get_theme_field() has been deprecated.

This method has been deprecated.

Loading history...
159
	}
160
161
	/**
162
	 * Stylesheet slug filter.
163
	 *
164
	 * @param string $stylesheet
165
	 *
166
	 * @deprecated
167
	 *
168
	 * @return string
169
	 */
170
	static function stylesheet( $stylesheet ) {
0 ignored issues
show
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
171
172
		return self::get_theme_field( 'Stylesheet', $stylesheet );
0 ignored issues
show
Deprecated Code introduced by
The method Toolbar_Theme_Switcher::get_theme_field() has been deprecated.

This method has been deprecated.

Loading history...
173
	}
174
175
	/**
176
	 * Returns field from theme data if cookie is set to valid theme.
177
	 *
178
	 * @param string $field_name
179
	 * @param mixed  $default
180
	 *
181
	 * @deprecated
182
	 *
183
	 * @return mixed
184
	 */
185
	static function get_theme_field( $field_name, $default = false ) {
0 ignored issues
show
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
186
187
		if ( ! empty( self::$theme ) ) {
188
			return self::$theme->get( $field_name );
189
		}
190
191
		return $default;
192
	}
193
194
	/**
195
	 * Retrieves allowed themes.
196
	 *
197
	 * @return array
198
	 */
199
	static function get_allowed_themes() {
0 ignored issues
show
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
200
201
		static $themes;
202
203
		if ( isset( $themes  ) ) {
204
			return $themes;
205
		}
206
207
		$wp_themes = wp_get_themes( array( 'allowed' => true ) );
208
209
		/** @var WP_Theme $theme */
210
		foreach ( $wp_themes as $theme ) {
211
212
			// make keys names (rather than slugs) for backwards compat
213
			$themes[ $theme->get( 'Name' ) ] = $theme;
214
		}
215
216
		$themes = apply_filters( 'tts_allowed_themes', $themes );
217
218
		return $themes;
219
	}
220
221
	/**
222
	 * Sets up hooks that doesn't need to happen early.
223
	 */
224
	static function init() {
0 ignored issues
show
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
225
226
		if ( self::can_switch_themes() ) {
227
			add_action( 'admin_bar_menu', array( __CLASS__, 'admin_bar_menu' ), 90 );
228
			add_action( 'wp_ajax_tts_set_theme', array( __CLASS__, 'set_theme' ) );
229
		}
230
231
		load_plugin_textdomain( 'toolbar-theme-switcher', false, dirname( plugin_basename( __FILE__ ) ) . '/lang' );
232
	}
233
234
	/**
235
	 * Creates menu in toolbar.
236
	 *
237
	 * @param WP_Admin_Bar $wp_admin_bar
238
	 */
239
	static function admin_bar_menu( $wp_admin_bar ) {
0 ignored issues
show
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
240
		$themes  = self::get_allowed_themes();
241
		$current = empty( self::$theme ) ? wp_get_theme() : self::$theme;
242
		$title   = apply_filters( 'tts_root_title', sprintf( __( 'Theme: %s', 'toolbar-theme-switcher' ), $current->display( 'Name' ) ) );
243
244
		$wp_admin_bar->add_menu( array(
245
			'id'    => 'toolbar_theme_switcher',
246
			'title' => $title,
247
			'href'  => admin_url( 'themes.php' ),
248
		) );
249
250
		/** @var WP_Theme $theme */
251
		foreach ( $themes as $theme ) {
252
			$wp_admin_bar->add_menu( array(
253
				'id'     => $theme['Stylesheet'],
254
				'title'  => $theme->display( 'Name' ),
255
				'href'   => $current == $theme ? null : add_query_arg( array( 'action' => 'tts_set_theme', 'theme' => urlencode( $theme->get_stylesheet() ) ), admin_url( 'admin-ajax.php' ) ),
256
				'parent' => 'toolbar_theme_switcher',
257
			) );
258
		}
259
	}
260
261
	/**
262
	 * Saves selected theme in cookie if valid.
263
	 */
264
	static function set_theme() {
0 ignored issues
show
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
265
266
		$stylesheet = $_REQUEST['theme'];
267
		$theme      = wp_get_theme( $stylesheet );
268
269
		if ( $theme->exists() && $theme->is_allowed() ) {
270
			setcookie( self::get_cookie_name(), $theme->get_stylesheet(), strtotime( '+1 year' ), COOKIEPATH );
271
		}
272
273
		wp_safe_redirect( wp_get_referer() );
274
		die;
0 ignored issues
show
Coding Style Compatibility introduced by
The method set_theme() contains an exit expression.

An exit expression should only be used in rare cases. For example, if you write a short command line script.

In most cases however, using an exit expression makes the code untestable and often causes incompatibilities with other libraries. Thus, unless you are absolutely sure it is required here, we recommend to refactor your code to avoid its usage.

Loading history...
275
	}
276
}