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

Re-implement logic for previewing WP_Query and introduce non-multiple postmeta #248

Merged
merged 15 commits into from
Sep 21, 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
3 changes: 2 additions & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ php:
- 7.0

env:
- WP_VERSION=4.5 WP_MULTISITE=0
- WP_VERSION=4.5 WP_MULTISITE=1
- WP_VERSION=latest WP_MULTISITE=0
- WP_VERSION=trunk WP_MULTISITE=0
- WP_VERSION=trunk WP_MULTISITE=1

Expand Down
21 changes: 10 additions & 11 deletions php/class-wp-customize-post-setting.php
Original file line number Diff line number Diff line change
Expand Up @@ -143,17 +143,16 @@ public function override_post_data( WP_Post &$post ) {

// Make sure that empty dates are not used in case of setting invalidity.
$empty_date = '0000-00-00 00:00:00';
if ( $empty_date === $post->post_date ) {
$post->post_date = current_time( 'mysql', false );
}
if ( $empty_date === $post->post_date_gmt ) {
$post->post_date_gmt = current_time( 'mysql', true );
}
if ( $empty_date === $post->post_modified ) {
$post->post_modified = current_time( 'mysql', false );
}
if ( $empty_date === $post->post_modified_gmt ) {
$post->post_modified_gmt = current_time( 'mysql', true );
$date_fields = array(
'post_date' => false,
'post_date_gmt' => true,
'post_modified' => false,
'post_modified_gmt' => true,
);
foreach ( $date_fields as $date_field => $gmt ) {
if ( $empty_date === $post->$date_field ) {
$post->$date_field = current_time( 'mysql', $gmt );
}
}

return false;
Expand Down
156 changes: 115 additions & 41 deletions php/class-wp-customize-postmeta-setting.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
*/
class WP_Customize_Postmeta_Setting extends WP_Customize_Setting {

const SETTING_ID_PATTERN = '/^postmeta\[(?P<post_type>[^\]]+)\]\[(?P<post_id>-?\d+)\]\[(?P<meta_key>.+)\]$/';
const SETTING_ID_PATTERN = '/^postmeta\[(?P<post_type>[^\]]+)\]\[(?P<post_id>\d+)\]\[(?P<meta_key>.+)\]$/';

const TYPE = 'postmeta';

Expand Down Expand Up @@ -47,6 +47,17 @@ class WP_Customize_Postmeta_Setting extends WP_Customize_Setting {
*/
public $meta_key;

/**
* Whether the value is mapped to a single postmeta row.
*
* If false, the value is expected to be an array and mapped to multiple postmeta rows.
*
* @todo This should be automatically sniffed from get_registered_meta_keys() since register_meta() now includes a 'single' param. See https://github.com/xwp/wp-customize-posts/pull/232
*
* @var bool
*/
public $single = true;

/**
* Posts component.
*
Expand Down Expand Up @@ -81,16 +92,20 @@ public function __construct( WP_Customize_Manager $manager, $id, $args = array()
}
$this->posts_component = $manager->posts;

if ( ! $this->single || ( isset( $args['single'] ) && false === $args['single'] ) ) {
if ( '' === $this->default ) {
$this->default = array();
}
if ( array() !== $this->default || ( isset( $args['default'] ) && array() !== $args['default'] ) ) {
_doing_it_wrong( __METHOD__, 'Plural postmeta may only have an empty array as the default', '0.8.0' );
}
$args['default'] = array();
}

// Determine the capability required for editing this.
$update = $args['post_id'] > 0;
$post_type_obj = get_post_type_object( $args['post_type'] );
$can_edit = false;
if ( $update ) {
$can_edit = $this->posts_component->current_user_can_edit_post( $args['post_id'] );
} elseif ( $post_type_obj ) {
$can_edit = current_user_can( $post_type_obj->cap->edit_posts );
}
if ( $can_edit && $update ) {
$can_edit = $this->posts_component->current_user_can_edit_post( $args['post_id'] );
if ( $can_edit ) {
$can_edit = current_user_can( 'edit_post_meta', $args['post_id'], $args['meta_key'] );
}
if ( ! $can_edit ) {
Expand Down Expand Up @@ -124,18 +139,25 @@ static function get_post_meta_setting_id( WP_Post $post, $meta_key ) {
public function value() {
$meta_key = $this->meta_key;
$object_id = $this->post_id;
$single = false;
$single = false; // For the sake of disambiguating empty values in filtering.
$values = get_post_meta( $object_id, $meta_key, $single );
$value = array_shift( $values );
if ( ! isset( $value ) ) {
$value = $this->default;

if ( $this->single ) {
$value = array_shift( $values );
if ( ! isset( $value ) ) {
$value = $this->default;
}
return $value;
} else {
return $values;
}
return $value;
}

/**
* Sanitize (and validate) an input.
*
* Note for non-single postmeta, the validation and sanitization callbacks will be applied on each item in the array.
*
* @see update_metadata()
* @access public
*
Expand All @@ -148,31 +170,47 @@ public function sanitize( $meta_value ) {
$meta_type = 'post';
$object_id = $this->post_id;
$meta_key = $this->meta_key;
$prev_value = ''; // Plural meta is not supported.

/**
* Filter a Customize setting value in form.
*
* @param mixed $meta_value Value of the setting.
* @param WP_Customize_Setting $this WP_Customize_Setting instance.
*/
$meta_value = apply_filters( "customize_sanitize_{$this->id}", $meta_value, $this );

// Apply sanitization if value didn't fail validation.
if ( ! is_wp_error( $meta_value ) && ! is_null( $meta_value ) ) {
$meta_value = sanitize_meta( $meta_key, $meta_value, $meta_type );
}
if ( is_wp_error( $meta_value ) ) {
return $has_setting_validation ? $meta_value : null;
$prev_value = ''; // Updating plural meta is not supported.

if ( $this->single ) {
$values = array( $meta_value );
} else {
if ( ! is_array( $meta_value ) ) {
return $has_setting_validation ? new WP_Error( 'expected_array', sprintf( __( 'Expected array value for non-single "%s" meta.', 'customize-posts' ), $meta_key ) ) : null;
}
$values = $meta_value;
}

/** This filter is documented in wp-includes/meta.php */
$check = apply_filters( "update_{$meta_type}_metadata", null, $object_id, $meta_key, $meta_value, $prev_value );
if ( null !== $check ) {
return $has_setting_validation ? new WP_Error( 'not_allowed', sprintf( __( 'Update to post meta "%s" blocked.', 'customize-posts' ), $meta_key ) ) : null;
foreach ( $values as &$value ) {

/**
* Filter a Customize setting value in form.
*
* @param mixed $value Value of the setting.
* @param WP_Customize_Setting $this WP_Customize_Setting instance.
*/
$value = apply_filters( "customize_sanitize_{$this->id}", $value, $this );

// Apply sanitization if value didn't fail validation.
if ( ! is_wp_error( $value ) && ! is_null( $value ) ) {
$value = sanitize_meta( $meta_key, $value, $meta_type );
}
if ( is_wp_error( $value ) ) {
return $has_setting_validation ? $value : null;
}

/** This filter is documented in wp-includes/meta.php */
$check = apply_filters( "update_{$meta_type}_metadata", null, $object_id, $meta_key, $value, $prev_value );
if ( null !== $check ) {
return $has_setting_validation ? new WP_Error( 'not_allowed', sprintf( __( 'Update to post meta "%s" blocked.', 'customize-posts' ), $meta_key ) ) : null;
}
}

return $meta_value;
if ( $this->single ) {
return array_shift( $values );
} else {
return $values;
}
}

/**
Expand Down Expand Up @@ -209,12 +247,48 @@ public function preview() {
* @return bool The result of saving the value.
*/
protected function update( $meta_value ) {
// Inserts are not supported yet.
if ( $this->post_id < 0 ) {
return false;
}

$result = update_post_meta( $this->post_id, $this->meta_key, $meta_value );
return ( false !== $result );
if ( $this->single ) {
$result = update_post_meta( $this->post_id, $this->meta_key, $meta_value );
return ( false !== $result );
} else {
if ( ! is_array( $meta_value ) ) {
return false;
}

// Non Serialized $meta_value Sync to reduce SQL overhead.
$meta_update = get_post_meta( $this->post_id, $this->meta_key, false );

$delete = array_diff( $meta_update, $meta_value );
if ( ! empty( $delete ) ) {
$delete = array_values( $delete );
}

$add = array_diff( $meta_value, $meta_update );
if ( ! empty( $add ) ) {
$add = array_values( $add );
}

$delete_count = count( $delete );
$add_count = count( $add );

// Update is faster than delete + insert (SQL).
for ( $i = 0; $i < $delete_count && $i < $add_count; $i ++ ) {
update_post_meta( $this->post_id, $this->meta_key, $add[ $i ], $delete[ $i ] );
unset( $add[ $i ], $delete[ $i ] );
}

// Delete if not updated.
foreach ( $delete as $id ) {
delete_post_meta( $this->post_id, $this->meta_key, $id );
}

// Add if not updated.
foreach ( $add as $item ) {
add_post_meta( $this->post_id, $this->meta_key, $item, false );
}

return true;
}
}
}
Loading