PluginProbe ʕ •ᴥ•ʔ
Code Manager / 1.0.37
Code Manager v1.0.37
1.0.47 trunk 1.0.0 1.0.1 1.0.10 1.0.11 1.0.12 1.0.13 1.0.14 1.0.15 1.0.16 1.0.17 1.0.18 1.0.19 1.0.2 1.0.20 1.0.21 1.0.22 1.0.23 1.0.24 1.0.25 1.0.26 1.0.27 1.0.28 1.0.3 1.0.30 1.0.31 1.0.32 1.0.33 1.0.34 1.0.35 1.0.36 1.0.37 1.0.38 1.0.39 1.0.4 1.0.40 1.0.41 1.0.42 1.0.43 1.0.44 1.0.45 1.0.46 1.0.5 1.0.6 1.0.7 1.0.8 1.0.9
code-manager / Code_Manager / Code_Manager.php
code-manager / Code_Manager Last commit date
Code_Manager.php 1 year ago Code_Manager_Dashboard.php 1 year ago Code_Manager_Export.php 1 year ago Code_Manager_Form.php 1 year ago Code_Manager_Import.php 1 year ago Code_Manager_Import_File.php 1 year ago Code_Manager_List.php 1 year ago Code_Manager_List_View.php 1 year ago Code_Manager_Model.php 1 year ago Code_Manager_Preview.php 1 year ago Code_Manager_Settings.php 1 year ago Code_Manager_Tabs.php 1 year ago Message_Box.php 1 year ago WP_List_Table.php 1 year ago
Code_Manager.php
381 lines
1 <?php
2
3 /**
4 * Code Manager main class
5 *
6 * @package Code_Manager
7 */
8 namespace Code_Manager;
9
10 /**
11 * Class Code_Manager
12 *
13 * Add plugin actions and runs the code saved in the code manager table.
14 *
15 * @author Peter Schulz
16 * @since 1.0.0
17 */
18 class Code_Manager {
19 const CM_MESSAGE = 'code_manager_alert_off';
20
21 const PHP_OPEN = '<?php';
22
23 const PHP_CLOSE = '?>';
24
25 const CSS_OPEN = '<style>';
26
27 const CSS_CLOSE = '</style>';
28
29 const JS_OPEN = '<script>';
30
31 const JS_CLOSE = '</script>';
32
33 /**
34 * Add Code Manager specific actions
35 *
36 * @param Object $loader Plugin loader.
37 * @since 1.0.0
38 */
39 public function add_actions( $loader ) {
40 $code_manager_model = null;
41 if ( null === $code_manager_model ) {
42 $code_manager_model = new Code_Manager_Model();
43 }
44 if ( is_admin() ) {
45 // Admin actions.
46 $loader->add_action( 'admin_action_code_manager_export', Code_Manager_Export::class, 'export' );
47 $loader->add_action( 'wp_ajax_code_manager_export', Code_Manager_Export::class, 'export_ajax' );
48 $loader->add_action( 'wp_ajax_nopriv_code_manager_export', Code_Manager_Export::class, 'export_ajax' );
49 $loader->add_action( 'wp_ajax_code_manager_update_code', $code_manager_model, 'update_code' );
50 $loader->add_action( 'wp_ajax_code_manager_activate_code', $code_manager_model, 'activate_code' );
51 $loader->add_action( 'wp_ajax_code_manager_activate_code_preview', $code_manager_model, 'activate_code_preview' );
52 $loader->add_action( 'wp_ajax_code_manager_deactivate_code_preview', $code_manager_model, 'deactivate_code_preview' );
53 $loader->add_action( 'wp_ajax_code_manager_reset_preview', $code_manager_model, 'reset_preview' );
54 $loader->add_action( 'wp_ajax_code_manager_get_code_list', $code_manager_model, 'get_code_list' );
55 $loader->add_action( 'wp_ajax_code_manager_code_name_exists', $code_manager_model, 'code_name_exists' );
56 $loader->add_action( 'wp_ajax_code_manager_is_code_preview_enabled', $code_manager_model, 'is_code_preview_enabled' );
57 $loader->add_action( 'wp_ajax_code_manager_get_code', $code_manager_model, 'get_code' );
58 $loader->add_action( 'wp_ajax_nopriv_code_manager_get_code', $code_manager_model, 'get_code' );
59 $loader->add_action( 'wp_ajax_code_manager_alert_off', Code_Manager::class, 'alert_off' );
60 }
61 }
62
63 /**
64 * Run shortcode
65 *
66 * @since 1.0.0
67 *
68 * @param array $atts Shortcode arguments.
69 * @var array
70 */
71 public function add_shortcode( $atts ) {
72 if ( self::code_manager_disabled() ) {
73 // Code manager disabled.
74 return '';
75 }
76 global $pagenow;
77 if ( 'post.php' === $pagenow || 'edit.php' === $pagenow || 'post-new.php' === $pagenow ) {
78 // Prevent errors on execution if shortcode is shown in classic editor.
79 return '';
80 }
81 if ( isset( $_SERVER['CONTENT_TYPE'] ) && 'application/json' === $_SERVER['CONTENT_TYPE'] ) {
82 // Prevent errors on execution if shortcode is shown in Gutenberg editor.
83 return null;
84 }
85 global $wpda_shortcode_args;
86 $wpda_shortcode_args = $atts;
87 // Allow user to define and use custom parameters.
88 $atts = array_change_key_case( (array) $atts, CASE_LOWER );
89 $wp_atts = shortcode_atts( array(
90 'id' => '',
91 'name' => '',
92 ), $atts );
93 if ( '' === $wp_atts['id'] && '' === $wp_atts['name'] ) {
94 return '';
95 }
96 ob_start();
97 $ids = explode( ',', $wp_atts['id'] );
98 foreach ( $ids as $id ) {
99 $this->run_shortcode_id( $id );
100 }
101 $names = explode( ',', $wp_atts['name'] );
102 foreach ( $names as $name ) {
103 $this->run_shortcode_name( $name );
104 }
105 $content = ob_get_contents();
106 ob_end_clean();
107 return $content;
108 }
109
110 /**
111 * Run shortcode from code id
112 *
113 * @param integer $id Code ID.
114 * @return void
115 */
116 protected function run_shortcode_id( $id ) {
117 if ( '' !== $id ) {
118 $code_manager_model = null;
119 if ( null === $code_manager_model ) {
120 $code_manager_model = new Code_Manager_Model();
121 }
122 $code_row = $code_manager_model::dml_query( $id );
123 if ( 1 === count( $code_row ) ) {
124 if ( '1' === $code_row[0]['code_enabled'] || Code_Manager_Preview::is_code_id_preview_enabled( $id ) ) {
125 $this->run_shortcode( $code_row[0]['code_type'], $code_row[0]['code'] );
126 }
127 }
128 }
129 }
130
131 /**
132 * Run shortcode from code name
133 *
134 * @param string $name Code name.
135 * @return void
136 */
137 protected function run_shortcode_name( $name ) {
138 if ( '' !== $name ) {
139 $code_manager_model = null;
140 if ( null === $code_manager_model ) {
141 $code_manager_model = new Code_Manager_Model();
142 }
143 $code_row = $code_manager_model::dml_query_by_name( $name );
144 if ( 1 === count( $code_row ) ) {
145 if ( '1' === $code_row[0]['code_enabled'] || Code_Manager_Preview::is_code_id_preview_enabled( $code_row[0]['code_id'] ) ) {
146 $this->run_shortcode( $code_row[0]['code_type'], $code_row[0]['code'] );
147 }
148 }
149 }
150 }
151
152 /**
153 * Adds code de pending on the code type
154 *
155 * @since 1.0.0
156 *
157 * @param string $code_type Code type (shortcodes only).
158 * @param string $code The code (PHP, JS, CSS or HTML).
159 */
160 protected function run_shortcode( $code_type, $code ) {
161 if ( strpos( $code_type, 'html' ) !== false ) {
162 echo wp_unslash( $code );
163 // phpcs:ignore WordPress.Security.EscapeOutput
164 } elseif ( strpos( $code_type, 'css' ) !== false ) {
165 echo self::CSS_OPEN . wp_unslash( $code ) . self::CSS_CLOSE;
166 // phpcs:ignore WordPress.Security.EscapeOutput
167 } elseif ( strpos( $code_type, 'javascript' ) !== false ) {
168 echo self::JS_OPEN . wp_unslash( $code ) . self::JS_CLOSE;
169 // phpcs:ignore WordPress.Security.EscapeOutput
170 } elseif ( 'php shortcode' === $code_type ) {
171 $this->add_php_code( $code );
172 }
173 }
174
175 /**
176 * Run shortcode from back-end code block using code id
177 *
178 * @param integer $id Code ID.
179 * @return void
180 */
181 public function run_shortcode_id_from_anywhere( $id ) {
182 $this->run_shortcode_id( $id );
183 }
184
185 /**
186 * Run shortcode from back-end code block using code name
187 *
188 * @param string $name Code name.
189 * @return void
190 */
191 public function run_shortcode_name_from_anywhere( $name ) {
192 $this->run_shortcode_name( $name );
193 }
194
195 /**
196 * Adds PHP code
197 *
198 * @since 1.0.0
199 *
200 * @param string $php_code PHP code to be added.
201 */
202 protected function add_php_code( $php_code ) {
203 if ( Code_Manager::is_code_manager_page() ) {
204 // Do not execute any code on Code Manager pages!!!
205 // This is an admins rescue in case code fails and locks a server.
206 } else {
207 $php_code_valid = true;
208 $php_code_functions = $this->get_classes_and_functions( $php_code );
209 foreach ( $php_code_functions['functions'] as $php_code_function ) {
210 if ( function_exists( $php_code_function ) ) {
211 var_dump( "ERROR: Function {$php_code_function} is already declared" );
212 $php_code_valid = false;
213 }
214 }
215 foreach ( $php_code_functions['classes'] as $php_code_class ) {
216 if ( class_exists( $php_code_class ) ) {
217 var_dump( "ERROR: Class {$php_code_class} is already declared" );
218 $php_code_valid = false;
219 }
220 }
221 if ( $php_code_valid ) {
222 try {
223 eval( $this->strip_code( $php_code ) );
224 } catch ( \ParseError $e ) {
225 echo $e->getMessage();
226 } catch ( \Throwable $e ) {
227 echo $e->getMessage();
228 }
229 }
230 }
231 }
232
233 protected function get_classes_and_functions( $php_code ) {
234 $tokens = token_get_all( $php_code );
235 $class_names = array();
236 $has_class_name = false;
237 $parsing_class = false;
238 $function_names = array();
239 $parsing_function = false;
240 $open_braces = 0;
241 foreach ( $tokens as $token ) {
242 $token_start = $token[0];
243 if ( T_CLASS === $token_start ) {
244 $parsing_class = true;
245 } elseif ( T_FUNCTION === $token_start ) {
246 if ( !$parsing_class ) {
247 $parsing_function = true;
248 }
249 } elseif ( T_STRING === $token_start ) {
250 if ( $parsing_function ) {
251 $parsing_function = false;
252 $function_names[] = $token[1];
253 } elseif ( $parsing_class && !$has_class_name ) {
254 $class_names[] = $token[1];
255 $has_class_name = true;
256 }
257 } elseif ( '(' === $token_start || ';' === $token_start ) {
258 $parsing_function = false;
259 } elseif ( '{' === $token_start ) {
260 if ( $parsing_class ) {
261 $open_braces++;
262 }
263 } elseif ( '}' === $token_start ) {
264 if ( $parsing_class ) {
265 $open_braces--;
266 if ( 0 === $open_braces ) {
267 $parsing_class = false;
268 }
269 }
270 }
271 }
272 return array(
273 'classes' => $class_names,
274 'functions' => $function_names,
275 );
276 }
277
278 /**
279 * Remove PHP opening and closing tags (when found) from given code
280 *
281 * @since 1.0.0
282 *
283 * @param string $php_code PHP source code.
284 *
285 * @return string PHP code without PHP opening and closing tags
286 */
287 protected function strip_code( $php_code ) {
288 $php_code = rtrim( ltrim( $php_code ) );
289 if ( self::PHP_OPEN === strtolower( substr( $php_code, 0, 5 ) ) ) {
290 $php_code = substr( $php_code, 5 );
291 }
292 if ( self::PHP_CLOSE === substr( $php_code, strlen( $php_code ) - 2 ) ) {
293 $php_code = substr( $php_code, 0, strlen( $php_code ) - 2 );
294 }
295 return $php_code;
296 }
297
298 /**
299 * Checks if Code Manager is disabled
300 *
301 * (1) Disabled in settings page
302 * (2) Disabled in config file
303 *
304 * @since 1.0.0
305 *
306 * @return bool TRUE - Code Manager is disabled
307 */
308 public static function code_manager_disabled() {
309 $plugin_code_execution = get_option( 'code_manager_plugin_code_execution' );
310 if ( false === $plugin_code_execution ) {
311 $plugin_code_execution = 'on';
312 }
313 return 'on' !== $plugin_code_execution || defined( 'CODE_MANAGER_DISABLED' ) && CODE_MANAGER_DISABLED;
314 }
315
316 /**
317 * Returns true if user is on a Code Manager back-end page
318 *
319 * @return bool
320 */
321 public static function is_code_manager_page() {
322 return is_admin() && isset( $_REQUEST['page'] ) && (CODE_MANAGER_MENU_SLUG === $_REQUEST['page'] || CODE_MANAGER_SETTINGS_MENU_SLUG === $_REQUEST['page'] || 'code_manager_post' === $_REQUEST['page']);
323 }
324
325 /**
326 * Get current user login
327 *
328 * @return string
329 */
330 public static function get_current_user_login() {
331 global $current_user;
332 if ( isset( $current_user->user_login ) ) {
333 return $current_user->user_login;
334 } else {
335 $wp_user = wp_get_current_user();
336 if ( isset( $wp_user->data->user_login ) ) {
337 return $wp_user->data->user_login;
338 } else {
339 return 'anonymous';
340 }
341 }
342 }
343
344 /**
345 * Get current user id
346 *
347 * @return string
348 */
349 public static function get_current_user_id() {
350 global $current_user;
351 if ( isset( $current_user->ID ) ) {
352 return $current_user->ID;
353 } else {
354 $wp_user = wp_get_current_user();
355 if ( isset( $wp_user->data->ID ) ) {
356 return $wp_user->data->ID;
357 } else {
358 return -1;
359 }
360 }
361 }
362
363 public static function get_cm_message() {
364 return get_user_meta( self::get_current_user_id(), self::CM_MESSAGE, true );
365 }
366
367 public static function alert_off() {
368 if ( is_user_logged_in() && isset( $_REQUEST['wpnonce'] ) ) {
369 // Check if action is allowed.
370 $wpnonce = sanitize_text_field( wp_unslash( $_REQUEST['wpnonce'] ) );
371 // input var okay.
372 if ( wp_verify_nonce( $wpnonce, 'code-manager-' . Code_manager::get_current_user_login() ) ) {
373 // Turn off alarm.
374 update_user_meta( self::get_current_user_id(), self::CM_MESSAGE, 'hide' );
375 }
376 }
377 wp_die();
378 }
379
380 }
381