PluginProbe
TablePress – Tables in WordPress made easy / 1.12
TablePress – Tables in WordPress made easy v1.12
3.3.4 3.3.3 3.3.2 3.3.1 trunk 1.12 1.14 1.9.2 2.0.4 2.1.7 2.1.8 2.2 2.2.1 2.2.2 2.2.3 2.2.4 2.2.5 2.3 2.3.1 2.3.2 2.4 2.4.1 2.4.2 2.4.3 2.4.4 All 44 releases
tablepress / classes / class-css.php

class-css.php in TablePress – Tables in WordPress made easy 1.12, at classes/class-css.php

447 lines 15.4 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * TablePress CSS Class
4 *
5 * @package TablePress
6 * @subpackage CSS
7 * @author Tobias Bäthge
8 * @since 1.1.0
9 */
10
11 // Prohibit direct script loading.
12 defined( 'ABSPATH' ) || die( 'No direct script access allowed!' );
13
14 /**
15 * TablePress CSS Class
16 * @package TablePress
17 * @subpackage CSS
18 * @author Tobias Bäthge
19 * @since 1.1.0
20 */
21 class TablePress_CSS {
22
23 /**
24 * Sanitize and tidy a string of CSS.
25 *
26 * @since 1.1.0
27 *
28 * @param string $css CSS code.
29 * @return string Sanitized and tidied CSS code.
30 */
31 public function sanitize_css( $css ) {
32 $csstidy = TablePress::load_class( 'TablePress_CSSTidy', 'class.csstidy.php', 'libraries/csstidy' );
33
34 // Sanitization and not just tidying for users without enough privileges.
35 if ( ! current_user_can( 'unfiltered_html' ) ) {
36 $csstidy->optimise = new TablePress_CSSTidy_custom_sanitize( $csstidy );
37
38 // Let "arrows" survive, otherwise this might be recognized as the beginning of an HTML tag and removed with other stuff behind it.
39 $css = str_replace( '<=', '&lt;=', $css );
40 // Remove all HTML tags.
41 $css = wp_kses( $css, 'strip' );
42 // KSES replaces single ">" with "&gt;", but ">" is valid in CSS selectors.
43 $css = str_replace( '&gt;', '>', $css );
44 // strip_tags again, because of the just added ">" (KSES for a second time would again bring the ">" problem).
45 $css = strip_tags( $css );
46 }
47
48 $csstidy->set_cfg( 'remove_bslash', false );
49 $csstidy->set_cfg( 'compress_colors', false );
50 $csstidy->set_cfg( 'compress_font-weight', false );
51 $csstidy->set_cfg( 'lowercase_s', false );
52 $csstidy->set_cfg( 'optimise_shorthands', false );
53 $csstidy->set_cfg( 'remove_last_;', false );
54 $csstidy->set_cfg( 'case_properties', false );
55 $csstidy->set_cfg( 'sort_properties', false );
56 $csstidy->set_cfg( 'sort_selectors', false );
57 $csstidy->set_cfg( 'discard_invalid_selectors', false );
58 $csstidy->set_cfg( 'discard_invalid_properties', true );
59 $csstidy->set_cfg( 'merge_selectors', false );
60 $csstidy->set_cfg( 'css_level', 'CSS3.0' );
61 $csstidy->set_cfg( 'preserve_css', true );
62 $csstidy->set_cfg( 'timestamp', false );
63 $csstidy->set_cfg( 'template', TABLEPRESS__DIR__ . '/libraries/csstidy/tablepress-standard.tpl' );
64
65 $csstidy->parse( $css );
66 return $csstidy->print->plain();
67 }
68
69 /**
70 * Minify a string of CSS code, that should have been sanitized/tidied before.
71 *
72 * @since 1.1.0
73 *
74 * @param string $css CSS code.
75 * @return string Minified CSS code.
76 */
77 public function minify_css( $css ) {
78 $csstidy = TablePress::load_class( 'TablePress_CSSTidy', 'class.csstidy.php', 'libraries/csstidy' );
79 $csstidy->optimise = new TablePress_CSSTidy_custom_sanitize( $csstidy );
80 $csstidy->set_cfg( 'remove_bslash', false );
81 $csstidy->set_cfg( 'compress_colors', true );
82 $csstidy->set_cfg( 'compress_font-weight', true );
83 $csstidy->set_cfg( 'lowercase_s', false );
84 $csstidy->set_cfg( 'optimise_shorthands', 1 );
85 $csstidy->set_cfg( 'remove_last_;', true );
86 $csstidy->set_cfg( 'case_properties', false );
87 $csstidy->set_cfg( 'sort_properties', false );
88 $csstidy->set_cfg( 'sort_selectors', false );
89 $csstidy->set_cfg( 'discard_invalid_selectors', false );
90 $csstidy->set_cfg( 'discard_invalid_properties', true );
91 $csstidy->set_cfg( 'merge_selectors', false );
92 $csstidy->set_cfg( 'css_level', 'CSS3.0' );
93 $csstidy->set_cfg( 'preserve_css', false );
94 $csstidy->set_cfg( 'timestamp', false );
95 $csstidy->set_cfg( 'template', 'highest' );
96
97 $csstidy->parse( $css );
98 return $csstidy->print->plain();
99 }
100
101 /**
102 * Get the location (file path or URL) of the "Custom CSS" file, depending on whether it's a Multisite install or not.
103 *
104 * @since 1.0.0
105 *
106 * @param string $type "normal" version, "minified" version, or "combined" (with TablePress Default CSS) version.
107 * @param string $location "path" or "url", for file path or URL.
108 * @return string Full file path or full URL for the "Custom CSS" file.
109 */
110 public function get_custom_css_location( $type, $location ) {
111 switch ( $type ) {
112 case 'combined':
113 $file = 'tablepress-combined.min.css';
114 break;
115 case 'minified':
116 $file = 'tablepress-custom.min.css';
117 break;
118 case 'normal':
119 default:
120 $file = 'tablepress-custom.css';
121 break;
122 }
123
124 if ( is_multisite() ) {
125 // Multisite installation: /wp-content/uploads/sites/<ID>/
126 $upload_location = wp_upload_dir();
127 } else {
128 // Singlesite installation: /wp-content/
129 $upload_location = array(
130 'basedir' => WP_CONTENT_DIR,
131 'baseurl' => content_url(),
132 );
133 }
134
135 switch ( $location ) {
136 case 'url':
137 $url = set_url_scheme( $upload_location['baseurl'] . '/' . $file );
138 /**
139 * Filter the URL from which the "Custom CSS" file is loaded.
140 *
141 * @since 1.0.0
142 *
143 * @param string $url URL of the "Custom CSS" file.
144 * @param string $file File name of the "Custom CSS" file.
145 * @param string $type Type of the "Custom CSS" file ("normal", "minified", or "combined").
146 */
147 $url = apply_filters( 'tablepress_custom_css_url', $url, $file, $type );
148 return $url;
149 // break; // unreachable
150 case 'path':
151 $path = $upload_location['basedir'] . '/' . $file;
152 /**
153 * Filter the file path on the server from which the "Custom CSS" file is loaded.
154 *
155 * @since 1.0.0
156 *
157 * @param string $path File path of the "Custom CSS" file.
158 * @param string $file File name of the "Custom CSS" file.
159 * @param string $type Type of the "Custom CSS" file ("normal", "minified", or "combined").
160 */
161 $path = apply_filters( 'tablepress_custom_css_file_name', $path, $file, $type );
162 return $path;
163 // break; // unreachable
164 }
165 }
166
167 /**
168 * Load the contents of the file with the "Custom CSS".
169 *
170 * @since 1.0.0
171 *
172 * @param string $type Optional. Whether to load "normal" version or "minified" version. Default "normal".
173 * @return string|bool Custom CSS on success, false on error.
174 */
175 public function load_custom_css_from_file( $type = 'normal' ) {
176 $filename = $this->get_custom_css_location( $type, 'path' );
177 // Check if file name is valid (0 means yes).
178 if ( 0 !== validate_file( $filename ) ) {
179 return false;
180 }
181 if ( ! @is_file( $filename ) ) {
182 return false;
183 }
184 if ( ! @is_readable( $filename ) ) {
185 return false;
186 }
187 return file_get_contents( $filename );
188 }
189
190 /**
191 * Load the contents of the file with the TablePress Default CSS.
192 *
193 * @since 1.1.0
194 *
195 * @return string|bool TablePress Default CSS on success, false on error.
196 */
197 public function load_default_css_from_file() {
198 $filename = TABLEPRESS_ABSPATH . 'css/default.min.css';
199 // Check if file name is valid (0 means yes).
200 if ( 0 !== validate_file( $filename ) ) {
201 return false;
202 }
203 if ( ! @is_file( $filename ) ) {
204 return false;
205 }
206 if ( ! @is_readable( $filename ) ) {
207 return false;
208 }
209 return file_get_contents( $filename );
210 }
211
212 /**
213 * Try to save "Custom CSS" to a file (requires "direct" method in WP_Filesystem, or stored FTP credentials).
214 *
215 * @since 1.1.0
216 *
217 * @param string $custom_css_normal Custom CSS code to be saved.
218 * @param string $custom_css_minified Minified CSS code to be saved.
219 * @return bool True on success, false on failure.
220 */
221 public function save_custom_css_to_file( $custom_css_normal, $custom_css_minified ) {
222 /**
223 * Filter whether the "Custom CSS" code shall be saved to a file on the server.
224 *
225 * @since 1.1.0
226 *
227 * @param bool $save Whether to save the "Custom CSS" to a file. Default true.
228 */
229 if ( ! apply_filters( 'tablepress_save_custom_css_to_file', true ) ) {
230 return false;
231 }
232
233 // Start capturing the output, to later prevent it.
234 ob_start();
235 $credentials = request_filesystem_credentials( '', '', false, false, null );
236 /*
237 * Do we have credentials already? (Otherwise the form will have been rendered, which is not supported here.)
238 * Or, if we have credentials, are they valid?
239 */
240 if ( false === $credentials || ! WP_Filesystem( $credentials ) ) {
241 ob_end_clean();
242 return false;
243 }
244
245 // We have valid access to the filesystem now -> try to save the files.
246 return $this->_custom_css_save_helper( $custom_css_normal, $custom_css_minified );
247 }
248
249 /**
250 * Save "Custom CSS" to files, delete "Custom CSS" files, or return HTML for the credentials form.
251 *
252 * Only used from "Plugin Options" screen, save_custom_css_to_file() is used in cases where no form output/redirection is possible (e.g. during plugin updates).
253 *
254 * @since 1.0.0
255 *
256 * @param string $custom_css_normal Custom CSS code to be saved. If empty, files will be deleted.
257 * @param string $custom_css_minified Minified CSS code to be saved.
258 * @return bool|string True on success, false on failure, or string of HTML for the credentials form for the WP_Filesystem API, if necessary.
259 */
260 public function save_custom_css_to_file_plugin_options( $custom_css_normal, $custom_css_minified ) {
261 /** This filter is documented in classes/class-css.php */
262 if ( ! apply_filters( 'tablepress_save_custom_css_to_file', true ) ) {
263 return false;
264 }
265
266 // Start capturing the output, to get HTML of the credentials form (if needed).
267 ob_start();
268 $credentials = request_filesystem_credentials( '', '', false, false, null );
269 // Do we have credentials already? (Otherwise the form will have been rendered already.)
270 if ( false === $credentials ) {
271 $form_data = ob_get_clean();
272 $form_data = str_replace( 'name="upgrade" id="upgrade" class="button"', 'name="upgrade" id="upgrade" class="button button-primary button-large"', $form_data );
273 return $form_data;
274 }
275
276 // We have received credentials, but don't know if they are valid yet.
277 if ( ! WP_Filesystem( $credentials ) ) {
278 // Credentials failed, so ask again (with $error flag true).
279 request_filesystem_credentials( '', '', true, false, null );
280 $form_data = ob_get_clean();
281 $form_data = str_replace( 'name="upgrade" id="upgrade" class="button"', 'name="upgrade" id="upgrade" class="button button-primary button-large"', $form_data );
282 return $form_data;
283 }
284
285 // We have valid access to the filesystem now -> try to save the files, or delete them if the "Custom CSS" is empty.
286 if ( '' !== $custom_css_normal ) {
287 return $this->_custom_css_save_helper( $custom_css_normal, $custom_css_minified );
288 } else {
289 return $this->_custom_css_delete_helper();
290 }
291 }
292
293 /**
294 * Save "Custom CSS" to files, if validated access to the WP_Filesystem exists.
295 *
296 * Helper function to prevent code duplication.
297 *
298 * @since 1.1.0
299 *
300 * @global WP_Filesystem_* $wp_filesystem WordPress file system abstraction object.
301 * @see save_custom_css_to_file()
302 * @see save_custom_css_to_file_plugin_options()
303 *
304 * @param string $custom_css_normal Custom CSS code to be saved.
305 * @param string $custom_css_minified Minified CSS code to be saved.
306 * @return bool True on success, false on failure.
307 */
308 protected function _custom_css_save_helper( $custom_css_normal, $custom_css_minified ) {
309 global $wp_filesystem;
310
311 /*
312 * WP_CONTENT_DIR and (FTP-)Content-Dir can be different (e.g. if FTP working dir is /).
313 * We need to account for that by replacing the path difference in the filename.
314 */
315 $path_difference = str_replace( $wp_filesystem->wp_content_dir(), '', trailingslashit( WP_CONTENT_DIR ) );
316
317 $css_types = array( 'normal', 'minified', 'combined' );
318
319 $default_css = $this->load_default_css_from_file();
320 if ( false === $default_css ) {
321 $default_css = '';
322 } else {
323 // Change relative URLs to web font files to absolute URLs, as combining the CSS files and saving to another directory breaks the relative URLs.
324 $absolute_path = plugins_url( 'css/tablepress.', TABLEPRESS__FILE__ );
325 // Make the absolute URL protocol-relative to prevent mixed content warnings.
326 $absolute_path = str_replace( array( 'http:', 'https:' ), '', $absolute_path );
327 $default_css = str_replace( 'url(tablepress.', 'url(' . $absolute_path, $default_css );
328 }
329 $file_content = array(
330 'normal' => $custom_css_normal,
331 'minified' => $custom_css_minified,
332 'combined' => $default_css . "\n" . $custom_css_minified,
333 );
334
335 $total_result = true; // whether all files were saved successfully
336 foreach ( $css_types as $css_type ) {
337 $filename = $this->get_custom_css_location( $css_type, 'path' );
338 // Check if filename is valid (0 means yes).
339 if ( 0 !== validate_file( $filename ) ) {
340 $total_result = false;
341 continue;
342 }
343 if ( '' !== $path_difference ) {
344 $filename = str_replace( $path_difference, '', $filename );
345 }
346 $result = $wp_filesystem->put_contents( $filename, $file_content[ $css_type ], FS_CHMOD_FILE );
347 $total_result = ( $total_result && $result );
348 }
349
350 $this->_flush_caching_plugins_css_minify_caches();
351
352 return $total_result;
353 }
354
355 /**
356 * Delete the "Custom CSS" files, if possible.
357 *
358 * @since 1.0.0
359 *
360 * @return bool True on success, false on failure.
361 */
362 public function delete_custom_css_files() {
363 // Start capturing the output, to later prevent it.
364 ob_start();
365 $credentials = request_filesystem_credentials( '', '', false, false, null );
366 /*
367 * Do we have credentials already? (Otherwise the form will have been rendered, which is not supported here.)
368 * Or, if we have credentials, are they valid?
369 */
370 if ( false === $credentials || ! WP_Filesystem( $credentials ) ) {
371 ob_end_clean();
372 return false;
373 }
374
375 // We have valid access to the filesystem now -> try to delete the files.
376 return $this->_custom_css_delete_helper();
377 }
378
379 /**
380 * Delete "Custom CSS" files, if validated access to the WP_Filesystem exists.
381 *
382 * Helper function to prevent code duplication
383 *
384 * @since 1.1.0
385 *
386 * @global WP_Filesystem_* $wp_filesystem WordPress file system abstraction object.
387 * @see delete_custom_css_files()
388 * @see save_custom_css_to_file_plugin_options()
389 *
390 * @return bool True on success, false on failure.
391 */
392 protected function _custom_css_delete_helper() {
393 global $wp_filesystem;
394
395 /*
396 * WP_CONTENT_DIR and (FTP-)Content-Dir can be different (e.g. if FTP working dir is /).
397 * We need to account for that by replacing the path difference in the filename.
398 */
399 $path_difference = str_replace( $wp_filesystem->wp_content_dir(), '', trailingslashit( WP_CONTENT_DIR ) );
400
401 $css_types = array( 'normal', 'minified', 'combined' );
402 $total_result = true; // whether all files were deleted successfully
403 foreach ( $css_types as $css_type ) {
404 $filename = $this->get_custom_css_location( $css_type, 'path' );
405 // Check if filename is valid (0 means yes).
406 if ( 0 !== validate_file( $filename ) ) {
407 $total_result = false;
408 continue;
409 }
410 if ( '' !== $path_difference ) {
411 $filename = str_replace( $path_difference, '', $filename );
412 }
413 // We have valid access to the filesystem now -> try to delete the file.
414 if ( $wp_filesystem->exists( $filename ) ) {
415 $result = $wp_filesystem->delete( $filename );
416 $total_result = ( $total_result && $result );
417 }
418 }
419
420 $this->_flush_caching_plugins_css_minify_caches();
421
422 return $total_result;
423 }
424
425 /**
426 * Flush the CSS minification cache of W3 Total Cache.
427 *
428 * @since 1.4.0
429 */
430 protected function _flush_caching_plugins_css_minify_caches() {
431 /** This filter is documented in models/model-table.php */
432 if ( ! apply_filters( 'tablepress_flush_caching_plugins_caches', true ) ) {
433 return;
434 }
435
436 // W3 Total Cache
437 if ( function_exists( 'w3tc_minify_flush' ) ) {
438 w3tc_minify_flush();
439 }
440 // WP Fastest Cache
441 if ( isset( $GLOBALS['wp_fastest_cache'] ) && method_exists( $GLOBALS['wp_fastest_cache'], 'deleteCache' ) ) {
442 $GLOBALS['wp_fastest_cache']->deleteCache( true );
443 }
444 }
445
446 } // class TablePress_CSS
447