diff --git a/class-fw-extension-shortcodes.php b/class-fw-extension-shortcodes.php index a47e29b..2f45db4 100644 --- a/class-fw-extension-shortcodes.php +++ b/class-fw-extension-shortcodes.php @@ -2,9 +2,16 @@ class FW_Extension_Shortcodes extends FW_Extension { - /** @var FW_Shortcode[] $shortcodes */ + /** + * @var FW_Shortcode[] + */ private $shortcodes; + /** + * @var FW_Ext_Shortcodes_Attr_Coder[] + */ + private $coders = array(); + /** * Gets a certain shortcode by a given tag * @@ -160,4 +167,53 @@ private function enqueue_shortcode_static( $shortcode ) { $this->enqueue_shortcodes_static($shortcode[5]); // inner shortcodes } } + + /** + * @param string $coder_id + * @return null|FW_Ext_Shortcodes_Attr_Coder|FW_Ext_Shortcodes_Attr_Coder[] + */ + public function get_attr_coder($coder_id = null) + { + if (empty($this->coders)) { + if (!class_exists('FW_Ext_Shortcodes_Attr_Coder')) { + require_once dirname(__FILE__) . '/includes/coder/interface-fw-ext-shortcodes-attr-coder.php'; + } + + if (!class_exists('FW_Ext_Shortcodes_Attr_Coder_JSON')) { + require_once dirname(__FILE__) . '/includes/coder/class-fw-ext-shortcodes-attr-coder-json.php'; + } + $coder_json = new FW_Ext_Shortcodes_Attr_Coder_JSON(); + $this->coders[ $coder_json->get_id() ] = $coder_json; + + if (!class_exists('FW_Ext_Shortcodes_Attr_Coder_Post_Meta')) { + require_once dirname(__FILE__) . '/includes/coder/class-fw-ext-shortcodes-attr-coder-post-meta.php'; + } + $coder_post_meta = new FW_Ext_Shortcodes_Attr_Coder_Post_Meta(); + $this->coders[ $coder_post_meta->get_id() ] = $coder_post_meta; + + foreach (apply_filters('fw_ext_shortcodes_coders', array()) as $coder) { + if (!($coder instanceof FW_Ext_Shortcodes_Attr_Coder)) { + trigger_error(get_class($coder) .' must implement FW_Ext_Shortcodes_Attr_Coder', E_USER_WARNING); + continue; + } + + if (isset($this->coders[ $coder->get_id() ])) { + trigger_error('Coder id='. $coder->get_id() .' is already defined', E_USER_WARNING); + continue; + } + + $this->coders[ $coder->get_id() ] = $coder; + } + } + + if (is_null($coder_id)) { + return $this->coders; + } else { + if (isset($this->coders[$coder_id])) { + return $this->coders[$coder_id]; + } else { + return null; + } + } + } } diff --git a/helpers.php b/helpers.php new file mode 100644 index 0000000..0ff5503 --- /dev/null +++ b/helpers.php @@ -0,0 +1,23 @@ +get_attr_coder() as $coder) { + if ($coder->can_decode($attributes, $shortcode_tag, $post_id)) { + return $coder->decode($attributes, $shortcode_tag, $post_id); + } + } + + return new WP_Error('coder_not_found', 'No decoder found'); +} diff --git a/includes/class-fw-shortcode.php b/includes/class-fw-shortcode.php index 46c0f6b..e64e399 100644 --- a/includes/class-fw-shortcode.php +++ b/includes/class-fw-shortcode.php @@ -139,8 +139,33 @@ public function _enqueue_static() { */ final public function render($atts, $content = null, $tag = '') { - $filtered_atts = apply_filters('fw_shortcode_atts', $atts, $content, $this->tag); - return $this->_render($filtered_atts, $content); + if (empty($atts)) { + $atts = array(); + } else { + if (version_compare(fw_ext('shortcodes')->manifest->get_version(), '1.3.0', '>=')) { + /** + * @var WP_Post $post + */ + global $post; + + if (!$post) { + return '

Shortcode attributes decode error: Global $post is required.

'; + } + + $atts = fw_ext_shortcodes_decode_attr($atts, $this->tag, $post->ID); + + if (is_wp_error($atts)) { + return '

Shortcode attributes decode error: ' . $atts->get_error_message() . '

'; + } + } else { + /** + * @deprecated Since Shortcodes 1.3.0 + */ + $atts = apply_filters('fw_shortcode_atts', $atts, $content, $this->tag); + } + } + + return $this->_render($atts, $content); } /** diff --git a/includes/coder/class-fw-ext-shortcodes-attr-coder-json.php b/includes/coder/class-fw-ext-shortcodes-attr-coder-json.php new file mode 100644 index 0000000..dfc656b --- /dev/null +++ b/includes/coder/class-fw-ext-shortcodes-attr-coder-json.php @@ -0,0 +1,99 @@ + $value) { + // the WordPress shortcode parser doesn't work when + // using attributes with dashes + $key = str_replace('-', '_', $key); + + if (is_array($value)) { + $value = json_encode($value); + $array_keys[$key] = $key; + } + + $encoded[$key] = $this->encode_value($value); + } + + if (!empty($array_keys)) { + $encoded['_array_keys'] = $this->encode_value(json_encode($array_keys)); + } + + $encoded['_made_with_builder'] = 'true'; + + return $encoded; + } + + private function encode_value($value) { + /** + * Replace '[' and ']' to fix http://bit.ly/1HoHVhl + * Replace new lines to fix http://bit.ly/1J887Om + * + * http://www.degraeve.com/reference/specialcharacters.php + */ + return str_replace( + array('[', ']', "\r\n"), + array('[', ']', ' '), + htmlentities($value, ENT_QUOTES, 'UTF-8') + ); + } + + /** + * @param array $attributes + * @param string $shortcode_tag + * @param int $post_id + * @return array|WP_Error + */ + public function decode(array $attributes, $shortcode_tag, $post_id) { + if (!$this->can_decode($attributes, $shortcode_tag, $post_id)) { + return $attributes; + } + + unset($attributes['_made_with_builder']); + + $array_keys = array(); + if (isset($attributes['_array_keys'])) { + $array_keys = json_decode($this->decode_value($attributes['_array_keys']), true); + unset($attributes['_array_keys']); + } + + $decoded = array(); + foreach ($attributes as $key => $value) { + $decoded[$key] = isset($array_keys[$key]) + ? json_decode($this->decode_value($value), true) + : $this->decode_value($value); + } + + return $decoded; + } + + private function decode_value($encoded_value) { + return html_entity_decode($encoded_value, ENT_QUOTES, 'UTF-8'); + } + + /** + * @param array $attributes + * @param string $shortcode_tag + * @param int $post_id + * @return bool + */ + public function can_decode(array $attributes, $shortcode_tag, $post_id) { + return isset($attributes['_made_with_builder']); // https://github.com/ThemeFuse/Unyson/issues/469 + } +} diff --git a/includes/coder/class-fw-ext-shortcodes-attr-coder-post-meta.php b/includes/coder/class-fw-ext-shortcodes-attr-coder-post-meta.php new file mode 100644 index 0000000..b368d74 --- /dev/null +++ b/includes/coder/class-fw-ext-shortcodes-attr-coder-post-meta.php @@ -0,0 +1,67 @@ +can_decode($attributes, $shortcode_tag, $post_id) ) { + return new WP_Error('cannot_decode', 'Cannot decode'); + } + + $option_values = json_decode( get_post_meta( $post_id, $this->meta_key, true ), true ); + $default_values = json_decode( get_post_meta( $post_id, $this->meta_key_defaults, true ), true ); + + $id = $attributes['fw_shortcode_id']; + $attributes = $default_values[ $shortcode_tag ]; + + if ( is_array( $option_values ) and false === empty( $option_values ) ) { + if ( preg_match( '/^[A-Za-z0-9]+$/', $id ) ) { + if ( isset( $option_values[ $shortcode_tag ][ $id ] ) ) { + $attributes = $option_values[ $shortcode_tag ][ $id ]; + } + } + } + + return $attributes; + } + + /** + * @param array $attributes + * @param string $shortcode_tag + * @param int $post_id + * @return bool + */ + public function can_decode(array $attributes, $shortcode_tag, $post_id) { + return isset($attributes['fw_shortcode_id']); // https://github.com/ThemeFuse/Unyson/issues/469 + } +} diff --git a/includes/coder/interface-fw-ext-shortcodes-attr-coder.php b/includes/coder/interface-fw-ext-shortcodes-attr-coder.php new file mode 100644 index 0000000..57dc77d --- /dev/null +++ b/includes/coder/interface-fw-ext-shortcodes-attr-coder.php @@ -0,0 +1,32 @@ + '1.2.14', + 'version' => '1.3.0', 'display' => false, 'standalone' => true, 'requirements' => array( diff --git a/shortcodes/text-block/options.php b/shortcodes/text-block/options.php index 1979973..af22ad4 100644 --- a/shortcodes/text-block/options.php +++ b/shortcodes/text-block/options.php @@ -9,5 +9,5 @@ 'reinit' => true, 'label' => __( 'Content', 'fw' ), 'desc' => __( 'Enter some content for this texblock', 'fw' ) - ) + ), ); diff --git a/shortcodes/text-block/views/view.php b/shortcodes/text-block/views/view.php index 6da64cb..d1623b2 100644 --- a/shortcodes/text-block/views/view.php +++ b/shortcodes/text-block/views/view.php @@ -5,6 +5,5 @@ /** * @var array $atts */ - ?> \ No newline at end of file