Skip to content
This repository has been archived by the owner on Dec 27, 2022. It is now read-only.

Store snapshot data in post_content instead of post_content_filtered #36

Merged
merged 1 commit into from
Jun 8, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .dev-lib
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
PATH_INCLUDES='*.* php js css tests'
WPCS_GIT_TREE=develop
ASSETS_DIR=wp-assets
123 changes: 115 additions & 8 deletions php/class-customize-snapshot-manager.php
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,8 @@ class Customize_Snapshot_Manager {
* @param Plugin $plugin Plugin instance.
*/
public function __construct( Plugin $plugin ) {
add_action( 'init', array( $this, 'create_post_type' ), 0 );

// Bail if our conditions are not met.
if ( ! ( ( isset( $_REQUEST['wp_customize'] ) && 'on' === $_REQUEST['wp_customize'] ) // WPCS: input var ok.
|| ( is_admin() && isset( $_SERVER['PHP_SELF'] ) && 'customize.php' === basename( $_SERVER['PHP_SELF'] ) ) // WPCS: input var ok; sanitization ok.
Expand Down Expand Up @@ -109,7 +111,6 @@ public function __construct( Plugin $plugin ) {

add_action( 'customize_controls_init', array( $this, 'set_return_url' ) );
add_action( 'init', array( $this, 'maybe_force_redirect' ), 0 );
add_action( 'init', array( $this, 'create_post_type' ), 0 );
add_action( 'customize_controls_enqueue_scripts', array( $this, 'enqueue_scripts' ) );
add_action( 'wp_ajax_customize_save', array( $this, 'set_snapshot_uuid' ), 0 );
add_action( 'wp_ajax_' . self::AJAX_ACTION, array( $this, 'update_snapshot' ) );
Expand Down Expand Up @@ -236,23 +237,129 @@ public function capture_unsanitized_snapshot_post_data() {
* @access public
*/
public function create_post_type() {
$labels = array(
'name' => _x( 'Snapshots', 'post type general name', 'customize-snapshots' ),
'singular_name' => _x( 'Snapshot', 'post type singular name', 'customize-snapshots' ),
'menu_name' => _x( 'Snapshots', 'admin menu', 'customize-snapshots' ),
'name_admin_bar' => _x( 'Snapshot', 'add new on admin bar', 'customize-snapshots' ),
'add_new' => _x( 'Add New', 'Customize Snapshot', 'customize-snapshots' ),
'add_new_item' => __( 'Add New Snapshot', 'customize-snapshots' ),
'new_item' => __( 'New Snapshot', 'customize-snapshots' ),
'edit_item' => __( 'Inspect Snapshot', 'customize-snapshots' ),
'view_item' => __( 'View Snapshot', 'customize-snapshots' ),
'all_items' => __( 'All Snapshots', 'customize-snapshots' ),
'search_items' => __( 'Search Snapshots', 'customize-snapshots' ),
'not_found' => __( 'No snapshots found.', 'customize-snapshots' ),
'not_found_in_trash' => __( 'No snapshots found in Trash.', 'customize-snapshots' ),
);

$args = array(
'labels' => array(
'name' => __( 'Customize Snapshots', 'customize-snapshots' ),
'singular_name' => __( 'Customize Snapshot', 'customize-snapshots' ),
),
'public' => false,
'labels' => $labels,
'description' => __( 'Customize Snapshots.', 'customize-snapshots' ),
'public' => true,
'capability_type' => 'post',
'publicly_queryable' => false,
'query_var' => false,
'exclude_from_search' => true,
'show_ui' => true,
'show_in_nav_menus' => false,
'show_in_menu' => true,
'show_in_admin_bar' => false,
'map_meta_cap' => true,
'hierarchical' => false,
'rewrite' => false,
'delete_with_user' => false,
'supports' => array( 'title', 'author', 'revisions' ),
'menu_position' => null,
'supports' => array( 'revisions' ),
'rewrite' => false,
'show_in_customizer' => false,
'menu_icon' => 'dashicons-camera',
'register_meta_box_cb' => array( $this, 'setup_metaboxes' ),
);

register_post_type( self::POST_TYPE, $args );
}

/**
* Add the metabox.
*/
function setup_metaboxes() {
$id = self::POST_TYPE;
$title = __( 'Data', 'customize-snapshots' );
$callback = array( $this, 'render_data_metabox' );
$screen = self::POST_TYPE;
$context = 'normal';
$priority = 'high';
add_meta_box( $id, $title, $callback, $screen, $context, $priority );
remove_meta_box( 'slugdiv', $screen, 'normal' );
}

/**
* Render the metabox.
*
* @param \WP_Post $post Post object.
*/
function render_data_metabox( $post ) {
$snapshot_content = static::get_post_content( $post );

echo '<h2><code>' . esc_html( $post->post_name ) . '</code></h2>';

$allowed_tags = array(
'details' => array( 'class' => true ),
'pre' => array( 'class' => true ),
'summary' => array(),
);
$rendered_content = sprintf( '<pre class="pre">%s</pre>', esc_html( static::encode_json( $snapshot_content ) ) );
echo wp_kses(
apply_filters( 'rendered_customize_snapshot_data', $rendered_content, $snapshot_content, $post ),
$allowed_tags
);
}

/**
* Get the snapshot array out of the post_content.
*
* A post revision for a customize_snapshot may also be supplied.
*
* @param \WP_Post $post A customize_snapshot post or a revision post.
* @return array
*/
static function get_post_content( \WP_Post $post ) {
if ( self::POST_TYPE !== $post->post_type ) {
$parent_post = null;
if ( 'revision' === $post->post_type ) {
$parent_post = get_post( $post->post_parent );
}
if ( ! $parent_post || self::POST_TYPE !== $parent_post->post_type ) {
return array();
}
}

// Snapshot is stored as JSON in post_content.
$snapshot = json_decode( $post->post_content, true );
if ( is_array( $snapshot ) ) {
return $snapshot;
}

return array();
}

/**
* Encode JSON with pretty formatting.
*
* @param array $value The snapshot value.
* @return string
*/
static function encode_json( $value ) {
$flags = 0;
if ( defined( '\JSON_PRETTY_PRINT' ) ) {
$flags |= \JSON_PRETTY_PRINT;
}
if ( defined( '\JSON_UNESCAPED_SLASHES' ) ) {
$flags |= \JSON_UNESCAPED_SLASHES;
}
return wp_json_encode( $value, $flags );
}

/**
* Enqueue styles & scripts for the Customizer.
*
Expand Down
41 changes: 37 additions & 4 deletions php/class-customize-snapshot.php
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,13 @@ class Customize_Snapshot {
*/
public $apply_dirty;

/**
* Whether kses filters on content_save_pre are added.
*
* @var bool
*/
protected $kses_suspended = false;

/**
* Initial loader.
*
Expand Down Expand Up @@ -101,7 +108,7 @@ public function __construct( Customize_Snapshot_Manager $snapshot_manager, $uuid

if ( $post ) {
// For reason why base64 encoding is used, see Customize_Snapshot::save().
$this->data = json_decode( $post->post_content_filtered, true );
$this->data = json_decode( $post->post_content, true );
if ( json_last_error() ) {
$this->snapshot_manager->plugin->trigger_warning( 'JSON parse error: ' . ( function_exists( 'json_last_error_msg' ) ? json_last_error_msg() : json_last_error() ) );
}
Expand Down Expand Up @@ -390,7 +397,7 @@ public function save( $status = 'draft' ) {
}

/**
* Filter the snapshot's data before it's saved to 'post_content_filtered'.
* Filter the snapshot's data before it's saved to 'post_content'.
*
* @param array $data Customizer settings and values.
* @return array
Expand All @@ -400,14 +407,15 @@ public function save( $status = 'draft' ) {
// JSON encoded snapshot data.
$post_content = wp_json_encode( $this->data, $options );

$this->suspend_kses();
if ( ! $this->post ) {
$postarr = array(
'post_type' => Customize_Snapshot_Manager::POST_TYPE,
'post_name' => $this->uuid,
'post_title' => $this->uuid,
'post_status' => $status,
'post_author' => get_current_user_id(),
'post_content_filtered' => $post_content,
'post_content' => $post_content,
);
$r = wp_insert_post( wp_slash( $postarr ), true );
if ( is_wp_error( $r ) ) {
Expand All @@ -419,15 +427,40 @@ public function save( $status = 'draft' ) {
$postarr = array(
'ID' => $this->post->ID,
'post_status' => $status,
'post_content_filtered' => wp_slash( $post_content ),
'post_content' => wp_slash( $post_content ),
);
$r = wp_update_post( $postarr, true );
if ( is_wp_error( $r ) ) {
return $r;
}
$this->post = get_post( $r );
}
$this->restore_kses();

return null;
}

/**
* Suspend kses which runs on content_save_pre and can corrupt JSON in post_content.
*
* @see \sanitize_post()
*/
function suspend_kses() {
if ( false !== has_filter( 'content_save_pre', 'wp_filter_post_kses' ) ) {
$this->kses_suspended = true;
kses_remove_filters();
}
}

/**
* Restore kses which runs on content_save_pre and can corrupt JSON in post_content.
*
* @see \sanitize_post()
*/
function restore_kses() {
if ( $this->kses_suspended ) {
kses_init_filters();
$this->kses_suspended = false;
}
}
}
4 changes: 2 additions & 2 deletions tests/php/test-class-customize-snapshot.php
Original file line number Diff line number Diff line change
Expand Up @@ -250,7 +250,7 @@ function test_save() {
$this->assertTrue( $snapshot->saved() );
$this->assertEquals( 'draft', $snapshot->status() );

$decoded = json_decode( $snapshot->post()->post_content_filtered, true );
$decoded = json_decode( $snapshot->post()->post_content, true );
$this->assertEquals( $decoded['foo'], $snapshot->get( $this->foo ) );
$this->assertEquals( $decoded['bar'], $snapshot->get( $this->bar ) );

Expand All @@ -259,7 +259,7 @@ function test_save() {
$snapshot->set( $this->bar, 'bar_custom', true );

$snapshot->save( 'publish' );
$decoded = json_decode( $snapshot->post()->post_content_filtered, true );
$decoded = json_decode( $snapshot->post()->post_content, true );
$this->assertEquals( $decoded['bar'], $snapshot->get( $this->bar ) );
$this->assertEquals( 'publish', $snapshot->status() );
}
Expand Down