Code Snippets - Version 2.5.0

Version Description

  • Added: Detect parse and fatal errors in code when saving a snippet, and display a user-friendly message
  • Fixed: Updated access of some methods in Code_Snippets_List_Table class to match updated WP_List_Table class
Download this release

Release Info

Developer bungeshea
Plugin Icon Code Snippets
Version 2.5.0
Comparing to
See all releases

Code changes from version 2.4.2 to 2.5.0

code-snippets.php CHANGED
@@ -7,7 +7,7 @@
7
  * contribute to the localization, please see https://github.com/sheabunge/code-snippets
8
  *
9
  * @package Code_Snippets
10
- * @version 2.4.2
11
  * @author Shea Bunge <http://bungeshea.com/>
12
  * @copyright Copyright (c) 2012-2015, Shea Bunge
13
  * @link https://github.com/sheabunge/code-snippets
@@ -20,7 +20,7 @@ Plugin URI: https://github.com/sheabunge/code-snippets
20
  Description: An easy, clean and simple way to add code snippets to your site. No need to edit to your theme's functions.php file again!
21
  Author: Shea Bunge
22
  Author URI: http://bungeshea.com
23
- Version: 2.4.2
24
  License: MIT
25
  License URI: license.txt
26
  Text Domain: code-snippets
@@ -42,7 +42,7 @@ if ( ! defined( 'ABSPATH' ) ) {
42
  * @since 2.0
43
  * @var string A PHP-standardized version number string
44
  */
45
- define( 'CODE_SNIPPETS_VERSION', '2.4.2' );
46
 
47
  /**
48
  * The full path to the main file of this plugin
7
  * contribute to the localization, please see https://github.com/sheabunge/code-snippets
8
  *
9
  * @package Code_Snippets
10
+ * @version 2.5.0
11
  * @author Shea Bunge <http://bungeshea.com/>
12
  * @copyright Copyright (c) 2012-2015, Shea Bunge
13
  * @link https://github.com/sheabunge/code-snippets
20
  Description: An easy, clean and simple way to add code snippets to your site. No need to edit to your theme's functions.php file again!
21
  Author: Shea Bunge
22
  Author URI: http://bungeshea.com
23
+ Version: 2.5.0
24
  License: MIT
25
  License URI: license.txt
26
  Text Domain: code-snippets
42
  * @since 2.0
43
  * @var string A PHP-standardized version number string
44
  */
45
+ define( 'CODE_SNIPPETS_VERSION', '2.5.0' );
46
 
47
  /**
48
  * The full path to the main file of this plugin
languages/code-snippets.pot CHANGED
@@ -6,9 +6,9 @@
6
  #, fuzzy
7
  msgid ""
8
  msgstr ""
9
- "Project-Id-Version: code-snippets 2.4.2\n"
10
  "Report-Msgid-Bugs-To: \n"
11
- "POT-Creation-Date: 2015-09-27 23:35+1000\n"
12
  "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
13
  "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
14
  "Language-Team: LANGUAGE <LL@li.org>\n"
@@ -18,7 +18,7 @@ msgstr ""
18
  "Content-Transfer-Encoding: 8bit\n"
19
  "Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\n"
20
 
21
- #: php/admin-menus/class-admin-menu.php:90
22
  msgid "You are not authorized to access this page."
23
  msgstr ""
24
 
@@ -35,63 +35,100 @@ msgstr ""
35
  msgid "Add New Snippet"
36
  msgstr ""
37
 
38
- #: php/admin-menus/class-edit-menu.php:201 php/class-list-table.php:324
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
39
  msgid "Description"
40
  msgstr ""
41
 
42
- #: php/admin-menus/class-edit-menu.php:231 php/class-list-table.php:325
43
  msgid "Tags"
44
  msgstr ""
45
 
46
- #: php/admin-menus/class-edit-menu.php:235
47
  msgid "Enter a list of tags; separated by commas"
48
  msgstr ""
49
 
50
- #: php/admin-menus/class-edit-menu.php:254
51
  msgid "Run snippet everywhere"
52
  msgstr ""
53
 
54
- #: php/admin-menus/class-edit-menu.php:255
55
  msgid "Only run in administration area"
56
  msgstr ""
57
 
58
- #: php/admin-menus/class-edit-menu.php:256
59
  msgid "Only run on site front-end"
60
  msgstr ""
61
 
62
- #: php/admin-menus/class-edit-menu.php:260
63
  msgid "Scope"
64
  msgstr ""
65
 
66
- #: php/admin-menus/class-edit-menu.php:280
67
  msgid "Sharing"
68
  msgstr ""
69
 
70
- #: php/admin-menus/class-edit-menu.php:284
71
  msgid "Allow this snippet to be activated on individual sites on the network"
72
  msgstr ""
73
 
74
- #: php/admin-menus/class-edit-menu.php:298
 
 
 
 
 
 
 
 
 
75
  msgid "An error occurred when saving the snippet."
76
  msgstr ""
77
 
78
- #: php/admin-menus/class-edit-menu.php:308
79
  msgid "Snippet <strong>added</strong>."
80
  msgstr ""
81
 
82
- #: php/admin-menus/class-edit-menu.php:309
83
  msgid "Snippet <strong>updated</strong>."
84
  msgstr ""
85
 
86
- #: php/admin-menus/class-edit-menu.php:310
87
  msgid "Snippet <strong>added</strong> and <strong>activated</strong>."
88
  msgstr ""
89
 
90
- #: php/admin-menus/class-edit-menu.php:311
91
  msgid "Snippet <strong>updated</strong> and <strong>activated</strong>."
92
  msgstr ""
93
 
94
- #: php/admin-menus/class-edit-menu.php:312
95
  msgid "Snippet <strong>updated</strong> and <strong>deactivated</strong>."
96
  msgstr ""
97
 
6
  #, fuzzy
7
  msgid ""
8
  msgstr ""
9
+ "Project-Id-Version: code-snippets 2.5.0\n"
10
  "Report-Msgid-Bugs-To: \n"
11
+ "POT-Creation-Date: 2015-10-08 19:35+1100\n"
12
  "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
13
  "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
14
  "Language-Team: LANGUAGE <LL@li.org>\n"
18
  "Content-Transfer-Encoding: 8bit\n"
19
  "Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\n"
20
 
21
+ #: php/admin-menus/class-admin-menu.php:95
22
  msgid "You are not authorized to access this page."
23
  msgstr ""
24
 
35
  msgid "Add New Snippet"
36
  msgstr ""
37
 
38
+ #: php/admin-menus/class-edit-menu.php:145
39
+ msgid "Don't Panic"
40
+ msgstr ""
41
+
42
+ #: php/admin-menus/class-edit-menu.php:146
43
+ #, php-format
44
+ msgid ""
45
+ "The code snippet you are trying to save produced a fatal error on line %d:"
46
+ msgstr ""
47
+
48
+ #: php/admin-menus/class-edit-menu.php:148
49
+ msgid ""
50
+ "The previous version of the snippet is unchanged, and the rest of this site "
51
+ "should be functioning normally as before."
52
+ msgstr ""
53
+
54
+ #: php/admin-menus/class-edit-menu.php:149
55
+ msgid ""
56
+ "Please use the back button in your browser to return to the previous page "
57
+ "and try to fix the code error."
58
+ msgstr ""
59
+
60
+ #: php/admin-menus/class-edit-menu.php:150
61
+ msgid ""
62
+ "If you prefer, you can close this page and discard the changes you just "
63
+ "made. No changes will be made to this site."
64
+ msgstr ""
65
+
66
+ #: php/admin-menus/class-edit-menu.php:270 php/class-list-table.php:324
67
  msgid "Description"
68
  msgstr ""
69
 
70
+ #: php/admin-menus/class-edit-menu.php:300 php/class-list-table.php:325
71
  msgid "Tags"
72
  msgstr ""
73
 
74
+ #: php/admin-menus/class-edit-menu.php:304
75
  msgid "Enter a list of tags; separated by commas"
76
  msgstr ""
77
 
78
+ #: php/admin-menus/class-edit-menu.php:323
79
  msgid "Run snippet everywhere"
80
  msgstr ""
81
 
82
+ #: php/admin-menus/class-edit-menu.php:324
83
  msgid "Only run in administration area"
84
  msgstr ""
85
 
86
+ #: php/admin-menus/class-edit-menu.php:325
87
  msgid "Only run on site front-end"
88
  msgstr ""
89
 
90
+ #: php/admin-menus/class-edit-menu.php:329
91
  msgid "Scope"
92
  msgstr ""
93
 
94
+ #: php/admin-menus/class-edit-menu.php:349
95
  msgid "Sharing"
96
  msgstr ""
97
 
98
+ #: php/admin-menus/class-edit-menu.php:353
99
  msgid "Allow this snippet to be activated on individual sites on the network"
100
  msgstr ""
101
 
102
+ #: php/admin-menus/class-edit-menu.php:406
103
+ #, php-format
104
+ msgid "The snippet has been deactivated due to an error on line %d:"
105
+ msgstr ""
106
+
107
+ #: php/admin-menus/class-edit-menu.php:411
108
+ msgid "The snippet has been deactivated due to an error in the code."
109
+ msgstr ""
110
+
111
+ #: php/admin-menus/class-edit-menu.php:418
112
  msgid "An error occurred when saving the snippet."
113
  msgstr ""
114
 
115
+ #: php/admin-menus/class-edit-menu.php:423
116
  msgid "Snippet <strong>added</strong>."
117
  msgstr ""
118
 
119
+ #: php/admin-menus/class-edit-menu.php:424
120
  msgid "Snippet <strong>updated</strong>."
121
  msgstr ""
122
 
123
+ #: php/admin-menus/class-edit-menu.php:425
124
  msgid "Snippet <strong>added</strong> and <strong>activated</strong>."
125
  msgstr ""
126
 
127
+ #: php/admin-menus/class-edit-menu.php:426
128
  msgid "Snippet <strong>updated</strong> and <strong>activated</strong>."
129
  msgstr ""
130
 
131
+ #: php/admin-menus/class-edit-menu.php:427
132
  msgid "Snippet <strong>updated</strong> and <strong>deactivated</strong>."
133
  msgstr ""
134
 
php/admin-menus/class-admin-menu.php CHANGED
@@ -61,19 +61,24 @@ class Code_Snippets_Admin_Menu {
61
 
62
  /**
63
  * Retrieve a result message based on a posted status
64
- * @return string|bool The result message if a valid status was recieved, otherwise false
 
 
 
 
 
65
  */
66
  protected function get_result_message( $messages, $request_var = 'result', $class = 'updated' ) {
67
 
68
  if ( empty( $_REQUEST[ $request_var ] ) ) {
69
- return;
70
  }
71
 
72
  $result = $_REQUEST[ $request_var ];
73
 
74
  if ( isset( $messages[ $result ] ) ) {
75
  return sprintf(
76
- '<div id="message" class="%1$s %2$s fade"><p>%1$s</p></div>',
77
  $messages[ $result ], $class
78
  );
79
  }
61
 
62
  /**
63
  * Retrieve a result message based on a posted status
64
+ *
65
+ * @param array $messages
66
+ * @param string $request_var
67
+ * @param string $class
68
+ *
69
+ * @return string|bool The result message if a valid status was received, otherwise false
70
  */
71
  protected function get_result_message( $messages, $request_var = 'result', $class = 'updated' ) {
72
 
73
  if ( empty( $_REQUEST[ $request_var ] ) ) {
74
+ return false;
75
  }
76
 
77
  $result = $_REQUEST[ $request_var ];
78
 
79
  if ( isset( $messages[ $result ] ) ) {
80
  return sprintf(
81
+ '<div id="message" class="%2$s fade"><p>%1$s</p></div>',
82
  $messages[ $result ], $class
83
  );
84
  }
php/admin-menus/class-edit-menu.php CHANGED
@@ -73,122 +73,191 @@ class Code_Snippets_Edit_Menu extends Code_Snippets_Admin_Menu {
73
  add_action( 'code_snippets/admin/single/settings', array( $this, 'render_multisite_sharing_setting' ) );
74
  }
75
 
76
- $this->save_posted_snippet();
77
  }
78
 
79
  /**
80
- * Save the posted snippet to the database
81
- * @uses wp_redirect() to pass the results to the page
82
- * @uses save_snippet() to save the snippet to the database
83
  */
84
- private function save_posted_snippet() {
85
 
86
- /* Make sure the nonce validates before we do any snippet ops */
87
  if ( ! isset( $_REQUEST['_wpnonce'] ) || ! wp_verify_nonce( $_REQUEST['_wpnonce'], 'save_snippet' ) ) {
88
  return;
89
  }
90
 
91
- /* Save the snippet if one has been submitted */
92
  if ( isset( $_POST['save_snippet'] ) || isset( $_POST['save_snippet_activate'] ) || isset( $_POST['save_snippet_deactivate'] ) ) {
 
 
93
 
94
- /* Build snippet object from fields with 'snippet_' prefix */
95
- $snippet = new Snippet();
96
- foreach ( $_POST as $field => $value ) {
97
- if ( 'snippet_' === substr( $field, 0, 8 ) ) {
98
 
99
- /* Remove 'snippet_' prefix from field name */
100
- $field = substr( $field, 8 );
101
- $snippet->$field = stripslashes( $value );
102
- }
 
103
  }
104
 
105
- /* Activate or deactivate the snippet before saving if we clicked the button */
 
 
 
 
 
106
 
107
- // Shared network snippets cannot be network activated
108
- if ( isset( $_POST['snippet_sharing'] ) && 'on' === $_POST['snippet_sharing'] ) {
109
- $snippet->active = 0;
110
- unset( $_POST['save_snippet_activate'], $_POST['save_snippet_deactivate'] );
111
- } elseif ( isset( $_POST['save_snippet_activate'] ) ) {
112
- $snippet->active = 1;
113
- } elseif ( isset( $_POST['save_snippet_deactivate'] ) ) {
114
- $snippet->active = 0;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
115
  }
116
 
117
- /* Save the snippet to the database */
118
- $snippet_id = save_snippet( $snippet );
 
119
 
120
- /* Update the shared network snippets if necessary */
121
- if ( $snippet_id && get_current_screen()->in_admin( 'network' ) ) {
122
- $shared_snippets = get_site_option( 'shared_network_snippets', array() );
123
 
124
- if ( isset( $_POST['snippet_sharing'] ) && 'on' === $_POST['snippet_sharing'] ) {
 
 
 
 
 
125
 
126
- /* Add the snippet ID to the array if it isn't already */
127
- if ( ! in_array( $snippet_id, $shared_snippets ) ) {
128
- $shared_snippets[] = $snippet_id;
129
- update_site_option( 'shared_network_snippets', array_values( $shared_snippets ) );
130
- }
131
- } elseif ( in_array( $snippet_id, $shared_snippets ) ) {
132
- /* Remove the snippet ID from the array */
133
- $shared_snippets = array_diff( $shared_snippets, array( $snippet_id ) );
134
- update_site_option( 'shared_network_snippets', array_values( $shared_snippets ) );
135
 
136
- /* Deactivate on all sites */
137
- global $wpdb;
138
- if ( $sites = $wpdb->get_col( "SELECT blog_id FROM $wpdb->blogs" ) ) {
 
 
 
 
 
139
 
140
- foreach ( $sites as $site ) {
141
- switch_to_blog( $site );
142
- $active_shared_snippets = get_option( 'active_shared_network_snippets' );
143
 
144
- if ( is_array( $active_shared_snippets ) ) {
145
- $active_shared_snippets = array_diff( $active_shared_snippets, array( $snippet_id ) );
146
- update_option( 'active_shared_network_snippets', $active_shared_snippets );
147
- }
148
- }
149
 
150
- restore_current_blog();
151
- }
152
 
153
- }
 
 
 
 
 
 
 
 
 
 
 
 
154
  }
 
155
 
156
- /* If the saved snippet ID is invalid, display an error message */
157
- if ( ! $snippet_id || $snippet_id < 1 ) {
158
- /* An error occurred */
159
- wp_redirect( add_query_arg( 'result', 'error', code_snippets_get_menu_url( 'add' ) ) );
160
- exit;
 
 
 
 
 
 
 
 
 
 
 
161
  }
 
162
 
163
- /* Set the result depending on if the snippet was just added */
164
- $result = isset( $_POST['snippet_id'] ) ? 'updated' : 'added';
165
 
166
- /* Append a suffix if the snippet was activated or deactivated */
167
- if ( isset( $_POST['save_snippet_activate'] ) ) {
168
- $result .= '-and-activated';
169
- } elseif ( isset( $_POST['save_snippet_deactivate'] ) ) {
170
- $result .= '-and-deactivated';
 
 
 
 
 
 
 
 
171
  }
 
172
 
173
- /* Redirect to edit snippet page */
 
 
 
 
 
 
 
 
174
  wp_redirect( add_query_arg(
175
- array( 'id' => $snippet_id, 'result' => $result ),
176
  code_snippets_get_menu_url( 'edit' )
177
  ) );
178
  exit;
179
  }
180
 
181
- /* Delete the snippet if the button was clicked */
182
- elseif ( isset( $_POST['snippet_id'], $_POST['delete_snippet'] ) ) {
183
- delete_snippet( $_POST['snippet_id'] );
184
- wp_redirect( add_query_arg( 'result', 'delete', code_snippets_get_menu_url( 'manage' ) ) );
185
- exit;
186
- }
187
 
188
- /* Export the snippet if the button was clicked */
189
- elseif ( isset( $_POST['snippet_id'], $_POST['export_snippet'] ) ) {
190
- export_snippets( $_POST['snippet_id'] );
 
 
191
  }
 
 
 
 
 
 
 
192
  }
193
 
194
  /**
@@ -288,30 +357,78 @@ class Code_Snippets_Edit_Menu extends Code_Snippets_Admin_Menu {
288
  <?php
289
  }
290
 
291
- /*
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
292
  * Print the status and error messages
293
  */
294
  protected function print_messages() {
295
 
296
- /* Check if an error exists, and if so, build the message */
297
- $error = $this->get_result_message(
298
- array( 'error' => __( 'An error occurred when saving the snippet.', 'code-snippets' ) ),
299
- 'result', 'error'
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
300
  );
301
 
302
- /* Output the error message if it exists, otherwise try to output a result message */
303
- if ( $error ) {
304
- echo $error;
305
- } else {
306
- echo $this->get_result_message(
307
- array(
308
- 'added' => __( 'Snippet <strong>added</strong>.', 'code-snippets' ),
309
- 'updated' => __( 'Snippet <strong>updated</strong>.', 'code-snippets' ),
310
- 'added-and-activated' => __( 'Snippet <strong>added</strong> and <strong>activated</strong>.', 'code-snippets' ),
311
- 'updated-and-activated' => __( 'Snippet <strong>updated</strong> and <strong>activated</strong>.', 'code-snippets' ),
312
- 'updated-and-deactivated' => __( 'Snippet <strong>updated</strong> and <strong>deactivated</strong>.', 'code-snippets' ),
313
- )
314
- );
315
  }
316
  }
317
 
73
  add_action( 'code_snippets/admin/single/settings', array( $this, 'render_multisite_sharing_setting' ) );
74
  }
75
 
76
+ $this->process_actions();
77
  }
78
 
79
  /**
80
+ * Process data sent from the edit page
 
 
81
  */
82
+ private function process_actions() {
83
 
84
+ /* Check for a valid nonce */
85
  if ( ! isset( $_REQUEST['_wpnonce'] ) || ! wp_verify_nonce( $_REQUEST['_wpnonce'], 'save_snippet' ) ) {
86
  return;
87
  }
88
 
 
89
  if ( isset( $_POST['save_snippet'] ) || isset( $_POST['save_snippet_activate'] ) || isset( $_POST['save_snippet_deactivate'] ) ) {
90
+ $this->save_posted_snippet();
91
+ }
92
 
93
+ if ( isset( $_POST['snippet_id'] ) ) {
 
 
 
94
 
95
+ /* Delete the snippet if the button was clicked */
96
+ if ( isset( $_POST['delete_snippet'] ) ) {
97
+ delete_snippet( $_POST['snippet_id'] );
98
+ wp_redirect( add_query_arg( 'result', 'delete', code_snippets_get_menu_url( 'manage' ) ) );
99
+ exit;
100
  }
101
 
102
+ /* Export the snippet if the button was clicked */
103
+ if ( isset( $_POST['export_snippet'] ) ) {
104
+ export_snippets( $_POST['snippet_id'] );
105
+ }
106
+ }
107
+ }
108
 
109
+ /**
110
+ * Remove the sharing status from a network snippet
111
+ * @param int $snippet_id
112
+ */
113
+ private function unshare_network_snippet( $snippet_id ) {
114
+ $shared_snippets = get_site_option( 'shared_network_snippets', array() );
115
+
116
+ if ( ! in_array( $snippet_id, $shared_snippets ) ) {
117
+ return;
118
+ }
119
+
120
+ /* Remove the snippet ID from the array */
121
+ $shared_snippets = array_diff( $shared_snippets, array( $snippet_id ) );
122
+ update_site_option( 'shared_network_snippets', array_values( $shared_snippets ) );
123
+
124
+ /* Deactivate on all sites */
125
+ global $wpdb;
126
+ if ( $sites = $wpdb->get_col( "SELECT blog_id FROM $wpdb->blogs" ) ) {
127
+
128
+ foreach ( $sites as $site ) {
129
+ switch_to_blog( $site );
130
+ $active_shared_snippets = get_option( 'active_shared_network_snippets' );
131
+
132
+ if ( is_array( $active_shared_snippets ) ) {
133
+ $active_shared_snippets = array_diff( $active_shared_snippets, array( $snippet_id ) );
134
+ update_option( 'active_shared_network_snippets', $active_shared_snippets );
135
+ }
136
  }
137
 
138
+ restore_current_blog();
139
+ }
140
+ }
141
 
142
+ private function code_error_callback( $out ) {
143
+ $error = error_get_last();
 
144
 
145
+ $m = '<h2>' . __( "Don't Panic", 'code-snippets' ) . '</h2>';
146
+ $m .= '<p>' . sprintf( __( 'The code snippet you are trying to save produced a fatal error on line %d:', 'code_snippets' ), $error['line'] ) . '</p>';
147
+ $m .= '<strong>' . $error['message'] . '</strong>';
148
+ $m .= '<p>' . __( 'The previous version of the snippet is unchanged, and the rest of this site should be functioning normally as before.' ) . '</p>';
149
+ $m .= '<p>' . __( 'Please use the back button in your browser to return to the previous page and try to fix the code error.', 'code-snippets' );
150
+ $m .= ' ' . __( 'If you prefer, you can close this page and discard the changes you just made. No changes will be made to this site.', 'code-snippets' ) . '</p>';
151
 
152
+ return $m;
153
+ }
 
 
 
 
 
 
 
154
 
155
+ /**
156
+ * Validate the snippet code before saving to database
157
+ *
158
+ * @param Snippet $snippet
159
+ *
160
+ * @return bool true if code produces errors
161
+ */
162
+ private function validate_code( Snippet $snippet ) {
163
 
164
+ if ( empty( $snippet->code ) ) {
165
+ return false;
166
+ }
167
 
168
+ ob_start( array( $this, 'code_error_callback' ) );
169
+ $result = eval( $snippet->code );
170
+ ob_end_clean();
 
 
171
 
172
+ return $result === false;
173
+ }
174
 
175
+ /**
176
+ * Save the posted snippet data to the database and redirect
177
+ */
178
+ private function save_posted_snippet() {
179
+
180
+ /* Build snippet object from fields with 'snippet_' prefix */
181
+ $snippet = new Snippet();
182
+ foreach ( $_POST as $field => $value ) {
183
+ if ( 'snippet_' === substr( $field, 0, 8 ) ) {
184
+
185
+ /* Remove 'snippet_' prefix from field name */
186
+ $field = substr( $field, 8 );
187
+ $snippet->$field = stripslashes( $value );
188
  }
189
+ }
190
 
191
+ /* Activate or deactivate the snippet before saving if we clicked the button */
192
+
193
+ // Shared network snippets cannot be network activated
194
+ if ( isset( $_POST['snippet_sharing'] ) && 'on' === $_POST['snippet_sharing'] ) {
195
+ $snippet->active = 0;
196
+ unset( $_POST['save_snippet_activate'], $_POST['save_snippet_deactivate'] );
197
+ } elseif ( isset( $_POST['save_snippet_activate'] ) ) {
198
+ $snippet->active = 1;
199
+ } elseif ( isset( $_POST['save_snippet_deactivate'] ) ) {
200
+ $snippet->active = 0;
201
+ }
202
+
203
+ /* Deactivate snippet if code contains errors */
204
+ if ( $snippet->active ) {
205
+ if ( $code_error = $this->validate_code( $snippet ) ) {
206
+ $snippet->active = 0;
207
  }
208
+ }
209
 
210
+ /* Save the snippet to the database */
211
+ $snippet_id = save_snippet( $snippet );
212
 
213
+ /* Update the shared network snippets if necessary */
214
+ if ( $snippet_id && get_current_screen()->in_admin( 'network' ) ) {
215
+
216
+ if ( isset( $_POST['snippet_sharing'] ) && 'on' === $_POST['snippet_sharing'] ) {
217
+ $shared_snippets = get_site_option( 'shared_network_snippets', array() );
218
+
219
+ /* Add the snippet ID to the array if it isn't already */
220
+ if ( ! in_array( $snippet_id, $shared_snippets ) ) {
221
+ $shared_snippets[] = $snippet_id;
222
+ update_site_option( 'shared_network_snippets', array_values( $shared_snippets ) );
223
+ }
224
+ } else {
225
+ $this->unshare_network_snippet( $snippet_id );
226
  }
227
+ }
228
 
229
+ /* If the saved snippet ID is invalid, display an error message */
230
+ if ( ! $snippet_id || $snippet_id < 1 ) {
231
+ /* An error occurred */
232
+ wp_redirect( add_query_arg( 'result', 'save-error', code_snippets_get_menu_url( 'add' ) ) );
233
+ exit;
234
+ }
235
+
236
+ /* Display message if a parse error occurred */
237
+ if ( isset( $code_error ) && $code_error ) {
238
  wp_redirect( add_query_arg(
239
+ array( 'id' => $snippet_id, 'result' => 'code-error' ),
240
  code_snippets_get_menu_url( 'edit' )
241
  ) );
242
  exit;
243
  }
244
 
245
+ /* Set the result depending on if the snippet was just added */
246
+ $result = isset( $_POST['snippet_id'] ) ? 'updated' : 'added';
 
 
 
 
247
 
248
+ /* Append a suffix if the snippet was activated or deactivated */
249
+ if ( isset( $_POST['save_snippet_activate'] ) ) {
250
+ $result .= '-and-activated';
251
+ } elseif ( isset( $_POST['save_snippet_deactivate'] ) ) {
252
+ $result .= '-and-deactivated';
253
  }
254
+
255
+ /* Redirect to edit snippet page */
256
+ wp_redirect( add_query_arg(
257
+ array( 'id' => $snippet_id, 'result' => $result ),
258
+ code_snippets_get_menu_url( 'edit' )
259
+ ) );
260
+ exit;
261
  }
262
 
263
  /**
357
  <?php
358
  }
359
 
360
+ /**
361
+ * Retrieve the first error in a snippet's code
362
+ *
363
+ * @param $snippet_id
364
+ *
365
+ * @return array|bool
366
+ */
367
+ private function get_snippet_error( $snippet_id ) {
368
+
369
+ if ( ! intval( $snippet_id ) ) {
370
+ return false;
371
+ }
372
+
373
+ $snippet = get_snippet( intval( $snippet_id ) );
374
+
375
+ if ( '' === $snippet->code ) {
376
+ return false;
377
+ }
378
+
379
+ @eval( $snippet->code );
380
+ $error = error_get_last();
381
+
382
+ if ( is_null( $error ) ) {
383
+ return false;
384
+ }
385
+
386
+ return $error;
387
+ }
388
+
389
+ /**
390
  * Print the status and error messages
391
  */
392
  protected function print_messages() {
393
 
394
+ if ( ! isset( $_REQUEST['result'] ) ) {
395
+ return;
396
+ }
397
+
398
+ $result = $_REQUEST['result'];
399
+
400
+ if ( 'code-error' === $result ) {
401
+
402
+ if ( isset( $_REQUEST['id'] ) && $error = $this->get_snippet_error( $_REQUEST['id'] ) ) {
403
+
404
+ printf(
405
+ '<div id="message" class="error fade"><p>%s</p><p><strong>%s</strong></p></div>',
406
+ sprintf( __( 'The snippet has been deactivated due to an error on line %d:', 'code-snippets' ), $error['line'] ),
407
+ $error['message']
408
+ );
409
+
410
+ } else {
411
+ echo '<div id="message" class="error fade"><p>', __( 'The snippet has been deactivated due to an error in the code.', 'code-snippets' ), '</p></div>';
412
+ }
413
+
414
+ return;
415
+ }
416
+
417
+ if ( 'save-error' === $result ) {
418
+ echo '<div id="message" class="error fade"><p>', __( 'An error occurred when saving the snippet.', 'code-snippets' ), '</p></div>';
419
+ return;
420
+ }
421
+
422
+ $messages = array(
423
+ 'added' => __( 'Snippet <strong>added</strong>.', 'code-snippets' ),
424
+ 'updated' => __( 'Snippet <strong>updated</strong>.', 'code-snippets' ),
425
+ 'added-and-activated' => __( 'Snippet <strong>added</strong> and <strong>activated</strong>.', 'code-snippets' ),
426
+ 'updated-and-activated' => __( 'Snippet <strong>updated</strong> and <strong>activated</strong>.', 'code-snippets' ),
427
+ 'updated-and-deactivated' => __( 'Snippet <strong>updated</strong> and <strong>deactivated</strong>.', 'code-snippets' ),
428
  );
429
 
430
+ if ( isset( $messages[ $result ] ) ) {
431
+ echo '<div id="message" class="updated fade"><p>', $messages[ $result ], '</p></div>';
 
 
 
 
 
 
 
 
 
 
 
432
  }
433
  }
434
 
php/class-list-table.php CHANGED
@@ -341,7 +341,7 @@ class Code_Snippets_List_Table extends WP_List_Table {
341
  *
342
  * @return array The IDs of the columns that can be sorted
343
  */
344
- protected function get_sortable_columns() {
345
  $sortable_columns = array(
346
  'id' => array( 'id', true ),
347
  'name' => array( 'name', false ),
@@ -364,7 +364,7 @@ class Code_Snippets_List_Table extends WP_List_Table {
364
  *
365
  * @return array An array of menu items with the ID paired to the label
366
  */
367
- protected function get_bulk_actions() {
368
  $actions = array(
369
  'activate-selected' => $this->is_network ? __( 'Network Activate', 'code-snippets' ) : __( 'Activate', 'code-snippets' ),
370
  'deactivate-selected' => $this->is_network ? __( 'Network Deactivate', 'code-snippets' ) : __( 'Deactivate', 'code-snippets' ),
@@ -382,7 +382,7 @@ class Code_Snippets_List_Table extends WP_List_Table {
382
  *
383
  * @return array The classes to include on the table element
384
  */
385
- protected function get_table_classes() {
386
  $classes = array( 'widefat', $this->_args['plural'] );
387
  return apply_filters( 'code_snippets/list_table/table_classes', $classes );
388
  }
@@ -394,7 +394,7 @@ class Code_Snippets_List_Table extends WP_List_Table {
394
  *
395
  * @return array A list of the view labels linked to the view
396
  */
397
- protected function get_views() {
398
  global $totals, $status;
399
  $status_links = array();
400
 
@@ -458,7 +458,7 @@ class Code_Snippets_List_Table extends WP_List_Table {
458
  * Add filters and extra actions above and below the table
459
  * @param string $which Are the actions displayed on the table top or bottom
460
  */
461
- protected function extra_tablenav( $which ) {
462
  global $status, $wpdb;
463
 
464
  if ( 'top' === $which ) {
341
  *
342
  * @return array The IDs of the columns that can be sorted
343
  */
344
+ public function get_sortable_columns() {
345
  $sortable_columns = array(
346
  'id' => array( 'id', true ),
347
  'name' => array( 'name', false ),
364
  *
365
  * @return array An array of menu items with the ID paired to the label
366
  */
367
+ public function get_bulk_actions() {
368
  $actions = array(
369
  'activate-selected' => $this->is_network ? __( 'Network Activate', 'code-snippets' ) : __( 'Activate', 'code-snippets' ),
370
  'deactivate-selected' => $this->is_network ? __( 'Network Deactivate', 'code-snippets' ) : __( 'Deactivate', 'code-snippets' ),
382
  *
383
  * @return array The classes to include on the table element
384
  */
385
+ public function get_table_classes() {
386
  $classes = array( 'widefat', $this->_args['plural'] );
387
  return apply_filters( 'code_snippets/list_table/table_classes', $classes );
388
  }
394
  *
395
  * @return array A list of the view labels linked to the view
396
  */
397
+ public function get_views() {
398
  global $totals, $status;
399
  $status_links = array();
400
 
458
  * Add filters and extra actions above and below the table
459
  * @param string $which Are the actions displayed on the table top or bottom
460
  */
461
+ public function extra_tablenav( $which ) {
462
  global $status, $wpdb;
463
 
464
  if ( 'top' === $which ) {
readme.txt CHANGED
@@ -4,7 +4,7 @@ Donate link: http://bungeshea.com/donate/
4
  Tags: code-snippets, snippets, code, php, network, multisite
5
  Requires at least: 3.6
6
  Tested up to: 4.3.2
7
- Stable tag: 2.4.2
8
  License: MIT
9
  License URI: license.txt
10
 
@@ -116,6 +116,10 @@ That's fantastic! Fork the [repository on GitHub](http://github.com/sheabunge/co
116
 
117
  == Changelog ==
118
 
 
 
 
 
119
  = 2.4.2 =
120
  * Added query variable to activate safe mode
121
  * Fixed settings not saving
@@ -375,6 +379,9 @@ __Fixed__
375
 
376
  == Upgrade Notice ==
377
 
 
 
 
378
  = 2.4.1 =
379
  Fixed CodeMirror themes not being detected on settings page
380
 
4
  Tags: code-snippets, snippets, code, php, network, multisite
5
  Requires at least: 3.6
6
  Tested up to: 4.3.2
7
+ Stable tag: 2.5.0
8
  License: MIT
9
  License URI: license.txt
10
 
116
 
117
  == Changelog ==
118
 
119
+ = 2.5.0 =
120
+ * Added: Detect parse and fatal errors in code when saving a snippet, and display a user-friendly message
121
+ * Fixed: Updated access of some methods in Code_Snippets_List_Table class to match updated WP_List_Table class
122
+
123
  = 2.4.2 =
124
  * Added query variable to activate safe mode
125
  * Fixed settings not saving
379
 
380
  == Upgrade Notice ==
381
 
382
+ = 2.5.0 =
383
+ Now detects errors in snippet code when saving
384
+
385
  = 2.4.1 =
386
  Fixed CodeMirror themes not being detected on settings page
387