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