From 2c820678807b680146eabebdaab6b72196f9bd6f Mon Sep 17 00:00:00 2001 From: Nathaniel Taintor Date: Thu, 29 Dec 2016 14:11:19 -0800 Subject: [PATCH 1/3] Optionally set checkbox values as 'true' or 'false' Adds the attribute option 'explicitbool' for checkboxes. If a checkbox is registered with 'explicitbool' => true, then the shortcode will be formatted with that attribute string like `attribute="false"` if unchecked. If the shortcode attributes are retrieved using the shortcode tag as the third parameter to `shortcode_atts()`, then this value will be converted back to a boolean automatically. This allows better handling of default values for attributes - otherwise, if an attribute was set with a default value of "true", then even if it was unchecked, the next time the shortcode was opened to edit, that default would be applied and the checkbox would be reset to checked. --- inc/class-shortcode-ui.php | 23 ++++++++++++++++++++++- js-tests/build/specs.js | 7 ++++++- js/build/shortcode-ui.js | 7 ++++++- js/src/models/shortcode.js | 7 ++++++- 4 files changed, 40 insertions(+), 4 deletions(-) diff --git a/inc/class-shortcode-ui.php b/inc/class-shortcode-ui.php index ef24728c..9830e255 100644 --- a/inc/class-shortcode-ui.php +++ b/inc/class-shortcode-ui.php @@ -427,7 +427,7 @@ public function handle_ajax_bulk_do_shortcode() { } /** - * Decode any encoded attributes. + * Decode any encoded attributes, and convert true/false strings to their boolean equivalents. * * @param array $out The output array of shortcode attributes. * @param array $pairs The supported attributes and their defaults. @@ -452,13 +452,34 @@ public function filter_shortcode_atts_decode_encoded( $out, $pairs, $atts ) { $default = isset( $fields[ $attr['type'] ]['encode'] ) ? $fields[ $attr['type'] ]['encode'] : false; $encoded = isset( $attr['encode'] ) ? $attr['encode'] : $default; + $explictbool = isset( $attr['explicitbool'] ) ? $attr['explicitbool'] : false; + if ( $encoded && isset( $out[ $attr['attr'] ] ) ) { $out[ $attr['attr'] ] = rawurldecode( $out[ $attr['attr'] ] ); } + + if ( $explicitbool && in_array( $out[ $attr['attr'] ], array( 'true', 'false' ) ) ) { + $out[ $attr['attr'] ] = $this->explicitbool( $out[ $attr['attr'] ] ); + } } return $out; } + /** + * Convert 'true' or 'false' strings to their boolean equivalent. + * + * @param string Expected to be either 'true' or 'false' + * @return bool + */ + private function explicitbool( $bool_string ) { + if ( 'true' === $bool_string ) { + return true; + } + if ( 'false' === $bool_string ) { + return false; + } + return null; + } } diff --git a/js-tests/build/specs.js b/js-tests/build/specs.js index 2852c840..56c6053f 100644 --- a/js-tests/build/specs.js +++ b/js-tests/build/specs.js @@ -833,7 +833,12 @@ Shortcode = Backbone.Model.extend({ this.get( 'attrs' ).each( function( attr ) { - // Skip empty attributes. + // Send 'true' and 'false' as checkbox values if 'explicitbool' option is on + if ( attr.get( 'explicitbool' ) && 'boolean' === typeof attr.get( 'value' ) ) { + attr.set( 'value', attr.get( 'value' ) ? 'true' : 'false' ); + } + + // Otherwise, skip empty or false attributes. if ( ! attr.get( 'value' ) || attr.get( 'value' ).length < 1 ) { return; } diff --git a/js/build/shortcode-ui.js b/js/build/shortcode-ui.js index a3c466f0..001e1811 100644 --- a/js/build/shortcode-ui.js +++ b/js/build/shortcode-ui.js @@ -204,7 +204,12 @@ Shortcode = Backbone.Model.extend({ this.get( 'attrs' ).each( function( attr ) { - // Skip empty attributes. + // Send 'true' and 'false' as checkbox values if 'explicitbool' option is on + if ( attr.get( 'explicitbool' ) && 'boolean' === typeof attr.get( 'value' ) ) { + attr.set( 'value', attr.get( 'value' ) ? 'true' : 'false' ); + } + + // Otherwise, skip empty or false attributes. if ( ! attr.get( 'value' ) || attr.get( 'value' ).length < 1 ) { return; } diff --git a/js/src/models/shortcode.js b/js/src/models/shortcode.js index c32c4aa0..29eb3005 100644 --- a/js/src/models/shortcode.js +++ b/js/src/models/shortcode.js @@ -68,7 +68,12 @@ Shortcode = Backbone.Model.extend({ this.get( 'attrs' ).each( function( attr ) { - // Skip empty attributes. + // Send 'true' and 'false' as checkbox values if 'explicitbool' option is on + if ( attr.get( 'explicitbool' ) && 'boolean' === typeof attr.get( 'value' ) ) { + attr.set( 'value', attr.get( 'value' ) ? 'true' : 'false' ); + } + + // Otherwise, skip empty or false attributes. if ( ! attr.get( 'value' ) || attr.get( 'value' ).length < 1 ) { return; } From ee29b73d24e5249ee734623fde5ddb6c33b848e2 Mon Sep 17 00:00:00 2001 From: Nathaniel Taintor Date: Thu, 29 Dec 2016 14:16:04 -0800 Subject: [PATCH 2/3] Fix typo in variable name --- inc/class-shortcode-ui.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/inc/class-shortcode-ui.php b/inc/class-shortcode-ui.php index 9830e255..f282179b 100644 --- a/inc/class-shortcode-ui.php +++ b/inc/class-shortcode-ui.php @@ -452,7 +452,7 @@ public function filter_shortcode_atts_decode_encoded( $out, $pairs, $atts ) { $default = isset( $fields[ $attr['type'] ]['encode'] ) ? $fields[ $attr['type'] ]['encode'] : false; $encoded = isset( $attr['encode'] ) ? $attr['encode'] : $default; - $explictbool = isset( $attr['explicitbool'] ) ? $attr['explicitbool'] : false; + $explicitbool = isset( $attr['explicitbool'] ) ? $attr['explicitbool'] : false; if ( $encoded && isset( $out[ $attr['attr'] ] ) ) { $out[ $attr['attr'] ] = rawurldecode( $out[ $attr['attr'] ] ); From e0ebbda3f29a54101f3aa0ae07bde426549fa889 Mon Sep 17 00:00:00 2001 From: Nathaniel Taintor Date: Thu, 29 Dec 2016 14:16:56 -0800 Subject: [PATCH 3/3] Strict in_array comparisons for PHPCS --- inc/class-shortcode-ui.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/inc/class-shortcode-ui.php b/inc/class-shortcode-ui.php index f282179b..1a54ce02 100644 --- a/inc/class-shortcode-ui.php +++ b/inc/class-shortcode-ui.php @@ -458,7 +458,7 @@ public function filter_shortcode_atts_decode_encoded( $out, $pairs, $atts ) { $out[ $attr['attr'] ] = rawurldecode( $out[ $attr['attr'] ] ); } - if ( $explicitbool && in_array( $out[ $attr['attr'] ], array( 'true', 'false' ) ) ) { + if ( $explicitbool && in_array( $out[ $attr['attr'] ], array( 'true', 'false' ), true ) ) { $out[ $attr['attr'] ] = $this->explicitbool( $out[ $attr['attr'] ] ); } }