This project does not seem to handle request data directly as such no vulnerable execution paths were found.
include
, or for example
via PHP's auto-loading mechanism.
These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php |
||
2 | |||
3 | /** |
||
4 | * Main plugin class. |
||
5 | */ |
||
6 | class Toolbar_Theme_Switcher { |
||
0 ignored issues
–
show
|
|||
7 | |||
8 | /** @var WP_Theme $theme */ |
||
9 | public static $theme = false; |
||
10 | |||
11 | /** |
||
12 | * Hooks that need to be set up early. |
||
13 | */ |
||
14 | public static function on_load() { |
||
15 | |||
16 | add_action( 'setup_theme', array( __CLASS__, 'setup_theme' ) ); |
||
17 | add_action( 'init', array( __CLASS__, 'init' ) ); |
||
18 | } |
||
19 | |||
20 | /** |
||
21 | * Loads cookie and sets up theme filters. |
||
22 | */ |
||
23 | public static function setup_theme() { |
||
24 | |||
25 | global $pagenow; |
||
0 ignored issues
–
show
Compatibility
Best Practice
introduced
by
Use of
global functionality is not recommended; it makes your code harder to test, and less reusable.
Instead of relying on 1. Pass all data via parametersfunction myFunction($a, $b) {
// Do something
}
2. Create a class that maintains your stateclass MyClass {
private $a;
private $b;
public function __construct($a, $b) {
$this->a = $a;
$this->b = $b;
}
public function myFunction() {
// Do something
}
}
![]() |
|||
26 | |||
27 | if ( ( is_admin() && 'themes.php' == $pagenow ) || ! self::can_switch_themes() ) { |
||
28 | return; |
||
29 | } |
||
30 | |||
31 | self::check_reset(); |
||
32 | self::load_cookie(); |
||
33 | |||
34 | if ( empty( self::$theme ) ) { |
||
35 | return; |
||
36 | } |
||
37 | |||
38 | add_filter( 'pre_option_template', array( self::$theme, 'get_template' ) ); |
||
39 | add_filter( 'pre_option_stylesheet', array( self::$theme, 'get_stylesheet' ) ); |
||
40 | add_filter( 'pre_option_stylesheet_root', array( self::$theme, 'get_theme_root' ) ); |
||
41 | $parent = self::$theme->parent(); |
||
42 | add_filter( 'pre_option_template_root', array( empty( $parent ) ? self::$theme : $parent, 'get_theme_root' ) ); |
||
43 | add_filter( 'pre_option_current_theme', '__return_false' ); |
||
44 | } |
||
45 | |||
46 | /** |
||
47 | * Clear theme choice if reset variable is present in request. |
||
48 | */ |
||
49 | public static function check_reset() { |
||
50 | |||
51 | if ( ! empty( filter_input( INPUT_GET, 'tts_reset' ) ) ) { |
||
52 | setcookie( self::get_cookie_name(), '', 1 ); |
||
53 | nocache_headers(); |
||
54 | wp_safe_redirect( home_url() ); |
||
55 | die; |
||
56 | } |
||
57 | } |
||
58 | |||
59 | /** |
||
60 | * If allowed to switch theme. |
||
61 | * |
||
62 | * @return boolean |
||
63 | */ |
||
64 | public static function can_switch_themes() { |
||
65 | |||
66 | $capability = apply_filters( 'tts_capability', 'switch_themes' ); |
||
67 | |||
68 | return apply_filters( 'tts_can_switch_themes', current_user_can( $capability ) ); |
||
69 | } |
||
70 | |||
71 | /** |
||
72 | * Sets if cookie is defined to non-default theme. |
||
73 | */ |
||
74 | public static function load_cookie() { |
||
75 | |||
76 | $theme_name = filter_input( INPUT_COOKIE, self::get_cookie_name() ); |
||
77 | |||
78 | if ( ! $theme_name ) { |
||
79 | return; |
||
80 | } |
||
81 | |||
82 | $theme = wp_get_theme( $theme_name ); |
||
83 | |||
84 | if ( |
||
85 | $theme->exists() |
||
86 | && $theme->get( 'Name' ) !== get_option( 'current_theme' ) |
||
87 | && $theme->is_allowed() |
||
88 | ) { |
||
89 | self::$theme = $theme; |
||
90 | } |
||
91 | } |
||
92 | |||
93 | /** |
||
94 | * Returns cookie name, based on home URL so it differs for sites in multisite. |
||
95 | * |
||
96 | * @return string |
||
97 | */ |
||
98 | public static function get_cookie_name() { |
||
99 | |||
100 | static $hash; |
||
101 | |||
102 | if ( empty( $hash ) ) { |
||
103 | $hash = 'wordpress_tts_theme_' . md5( home_url( '', 'http' ) ); |
||
104 | } |
||
105 | |||
106 | return $hash; |
||
107 | } |
||
108 | |||
109 | /** |
||
110 | * Retrieves allowed themes. |
||
111 | * |
||
112 | * @return WP_Theme[] |
||
113 | */ |
||
114 | public static function get_allowed_themes() { |
||
115 | |||
116 | static $themes; |
||
117 | |||
118 | if ( isset( $themes ) ) { |
||
119 | return $themes; |
||
120 | } |
||
121 | |||
122 | $wp_themes = wp_get_themes( array( 'allowed' => true ) ); |
||
123 | |||
124 | /** @var WP_Theme $theme */ |
||
125 | foreach ( $wp_themes as $theme ) { |
||
126 | |||
127 | // Make keys names (rather than slugs) for backwards compat. |
||
128 | $themes[ $theme->get( 'Name' ) ] = $theme; |
||
129 | } |
||
130 | |||
131 | $themes = apply_filters( 'tts_allowed_themes', $themes ); |
||
132 | |||
133 | return $themes; |
||
134 | } |
||
135 | |||
136 | /** |
||
137 | * Sets up hooks that doesn't need to happen early. |
||
138 | */ |
||
139 | public static function init() { |
||
140 | |||
141 | if ( self::can_switch_themes() ) { |
||
142 | add_action( 'admin_bar_menu', array( __CLASS__, 'admin_bar_menu' ), 90 ); |
||
143 | add_action( 'wp_ajax_tts_set_theme', array( __CLASS__, 'set_theme' ) ); |
||
144 | } |
||
145 | |||
146 | load_plugin_textdomain( 'toolbar-theme-switcher', false, dirname( dirname( plugin_basename( __FILE__ ) ) ) . '/lang' ); |
||
147 | } |
||
148 | |||
149 | /** |
||
150 | * Creates menu in toolbar. |
||
151 | * |
||
152 | * @param WP_Admin_Bar $wp_admin_bar Admin bar instance. |
||
153 | */ |
||
154 | public static function admin_bar_menu( $wp_admin_bar ) { |
||
155 | $themes = self::get_allowed_themes(); |
||
156 | $current = empty( self::$theme ) ? wp_get_theme() : self::$theme; |
||
157 | unset( $themes[ $current->get( 'Name' ) ] ); |
||
158 | uksort( $themes, array( __CLASS__, 'sort_core_themes' ) ); |
||
159 | |||
160 | $title = apply_filters( 'tts_root_title', sprintf( __( 'Theme: %s', 'toolbar-theme-switcher' ), $current->display( 'Name' ) ) ); |
||
161 | |||
162 | $wp_admin_bar->add_menu( array( |
||
163 | 'id' => 'toolbar_theme_switcher', |
||
164 | 'title' => $title, |
||
165 | 'href' => admin_url( 'themes.php' ), |
||
166 | ) ); |
||
167 | |||
168 | $ajax_url = admin_url( 'admin-ajax.php' ); |
||
169 | |||
170 | foreach ( $themes as $theme ) { |
||
171 | |||
172 | $href = add_query_arg( array( |
||
173 | 'action' => 'tts_set_theme', |
||
174 | 'theme' => urlencode( $theme->get_stylesheet() ), |
||
175 | ), $ajax_url ); |
||
176 | |||
177 | $wp_admin_bar->add_menu( array( |
||
178 | 'id' => $theme['Stylesheet'], |
||
179 | 'title' => $theme->display( 'Name' ), |
||
180 | 'href' => $href, |
||
181 | 'parent' => 'toolbar_theme_switcher', |
||
182 | ) ); |
||
183 | } |
||
184 | } |
||
185 | |||
186 | /** |
||
187 | * Callback to sort theme array with core themes in numerical order by year. |
||
188 | * |
||
189 | * @param string $theme_a First theme name. |
||
190 | * @param string $theme_b Second theme name. |
||
191 | * |
||
192 | * @return int |
||
193 | */ |
||
194 | public static function sort_core_themes( $theme_a, $theme_b ) { |
||
195 | |||
196 | static $twenties = array( |
||
197 | 'Twenty Ten', |
||
198 | 'Twenty Eleven', |
||
199 | 'Twenty Twelve', |
||
200 | 'Twenty Thirteen', |
||
201 | 'Twenty Fourteen', |
||
202 | 'Twenty Fifteen', |
||
203 | 'Twenty Sixteen', |
||
204 | 'Twenty Seventeen', |
||
205 | 'Twenty Eighteen', |
||
206 | 'Twenty Nineteen', |
||
207 | 'Twenty Twenty', |
||
208 | ); |
||
209 | |||
210 | if ( 0 === strpos( $theme_a, 'Twenty' ) && 0 === strpos( $theme_b, 'Twenty' ) ) { |
||
211 | |||
212 | $index_a = array_search( $theme_a, $twenties, true ); |
||
213 | $index_b = array_search( $theme_b, $twenties, true ); |
||
214 | |||
215 | if ( false !== $index_a && false !== $index_b ) { |
||
216 | return ( $index_a < $index_b ) ? - 1 : 1; |
||
217 | } |
||
218 | } |
||
219 | |||
220 | return strcasecmp( $theme_a, $theme_b ); |
||
221 | } |
||
222 | |||
223 | /** |
||
224 | * Saves selected theme in cookie if valid. |
||
225 | */ |
||
226 | public static function set_theme() { |
||
227 | |||
228 | $stylesheet = filter_input( INPUT_GET, 'theme' ); |
||
229 | $theme = wp_get_theme( $stylesheet ); |
||
230 | |||
231 | if ( $theme->exists() && $theme->is_allowed() ) { |
||
232 | setcookie( self::get_cookie_name(), $theme->get_stylesheet(), strtotime( '+1 year' ), COOKIEPATH ); |
||
233 | } |
||
234 | |||
235 | wp_safe_redirect( wp_get_referer() ); |
||
236 | die; |
||
0 ignored issues
–
show
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 ![]() |
|||
237 | } |
||
238 | |||
239 | // <editor-fold desc="Deprecated"> |
||
240 | /** |
||
241 | * If theme is in list of allowed to be switched to. |
||
242 | * |
||
243 | * @deprecated :2.0 |
||
244 | * |
||
245 | * @param WP_Theme $theme |
||
246 | * |
||
247 | * @return bool |
||
248 | */ |
||
249 | public static function is_allowed( $theme ) { |
||
250 | |||
251 | return array_key_exists( $theme->get( 'Name' ), self::get_allowed_themes() ); |
||
252 | } |
||
253 | |||
254 | /** |
||
255 | * Template slug filter. |
||
256 | * |
||
257 | * @param string $template |
||
258 | * |
||
259 | * @deprecated :2.0 |
||
260 | * |
||
261 | * @return string |
||
262 | */ |
||
263 | public static function template( $template ) { |
||
264 | |||
265 | return self::get_theme_field( 'Template', $template ); |
||
0 ignored issues
–
show
The method
Toolbar_Theme_Switcher::get_theme_field() has been deprecated with message: :2.0
This method has been deprecated. The supplier of the class has supplied an explanatory message. The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead. ![]() |
|||
266 | } |
||
267 | |||
268 | /** |
||
269 | * Stylesheet slug filter. |
||
270 | * |
||
271 | * @param string $stylesheet |
||
272 | * |
||
273 | * @deprecated :2.0 |
||
274 | * |
||
275 | * @return string |
||
276 | */ |
||
277 | public static function stylesheet( $stylesheet ) { |
||
278 | |||
279 | return self::get_theme_field( 'Stylesheet', $stylesheet ); |
||
0 ignored issues
–
show
The method
Toolbar_Theme_Switcher::get_theme_field() has been deprecated with message: :2.0
This method has been deprecated. The supplier of the class has supplied an explanatory message. The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead. ![]() |
|||
280 | } |
||
281 | |||
282 | /** |
||
283 | * Returns field from theme data if cookie is set to valid theme. |
||
284 | * |
||
285 | * @param string $field_name |
||
286 | * @param mixed $default |
||
287 | * |
||
288 | * @deprecated :2.0 |
||
289 | * |
||
290 | * @return mixed |
||
291 | */ |
||
292 | public static function get_theme_field( $field_name, $default = false ) { |
||
293 | |||
294 | if ( ! empty( self::$theme ) ) { |
||
295 | return self::$theme->get( $field_name ); |
||
296 | } |
||
297 | |||
298 | return $default; |
||
299 | } |
||
300 | // </editor-fold> |
||
301 | } |
||
302 |
You can fix this by adding a namespace to your class:
When choosing a vendor namespace, try to pick something that is not too generic to avoid conflicts with other libraries.