Skip to content
This repository was archived by the owner on Dec 16, 2022. It is now read-only.
Open
2 changes: 1 addition & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ php:
env:
- WP_VERSION=trunk WP_MULTISITE=0
- WP_VERSION=latest WP_MULTISITE=0
- WP_VERSION=4.6.1 WP_MULTISITE=0
- WP_VERSION=4.7.5 WP_MULTISITE=0
- WP_VERSION=latest WP_MULTISITE=1

install:
Expand Down
66 changes: 66 additions & 0 deletions js/customize-post-section.js
Original file line number Diff line number Diff line change
Expand Up @@ -282,6 +282,9 @@
section.addStatusControl();
section.addDateControl();
}
if ( api.Posts.data.themeSupports['post-formats'] && postTypeObj.supports['post-formats'] ) {
section.addPostFormatControl();
}
if ( postTypeObj.supports['page-attributes'] || postTypeObj.supports.parent ) {
section.addParentControl();
}
Expand Down Expand Up @@ -633,6 +636,69 @@
return control;
},

/**
* Add post format control.
*
* @todo Move this into a separate file/component like Page Template and Featured Image.
*
* @see post_format_meta_box() in PHP.
*
* @returns {wp.customize.Control} Added control.
*/
addPostFormatControl: function addPostFormatControl() {
var section = this, control, settingId, setting, controlId, postTypeObj, postFormats;

postTypeObj = api.Posts.data.postTypes[ section.params.post_type ];
if ( ! api.Posts.data.themeSupports['post-formats'] || ! postTypeObj.supports['post-formats'] ) {
return null;
}

settingId = 'post_terms[' + section.params.post_type + '][' + String( section.params.post_id ) + '][post_format]';
setting = api( settingId );
if ( ! setting ) {
return null;
}

// Add in the current one if it isn't there yet, in case the current theme doesn't support it
postFormats = _.uniq(
[ 'standard' ].concat( api.Posts.data.themeSupports['post-formats'] ).concat( [ setting.get() ] )
);

controlId = section.id + '[post_format]';
control = new api.controlConstructor.dynamic( controlId, {
params: {
section: section.id,
priority: 65,
label: postTypeObj.labels.post_format_field || api.Posts.data.l10n.fieldPostFormatLabel,
active: true,
settings: {
'default': setting.id
},
field_type: 'select',
input_attrs: {
'data-customize-setting-link': settingId // @todo The need for this needs to be eliminated in core.
},
choices: _.map( postFormats, function( postFormat ) {
return {
text: api.Posts.data.l10n.postFormatStrings[ postFormat ] || postFormat,
value: postFormat
};
} )
}
} );

// Override preview trying to de-activate control not present in preview context.
control.active.validate = function() {
return true;
};

// Register.
section.postFieldControls.post_format = control;
api.control.add( control.id, control );

return control;
},

/**
* Add parent control.
*
Expand Down
28 changes: 17 additions & 11 deletions js/customize-posts.js
Original file line number Diff line number Diff line change
Expand Up @@ -73,30 +73,36 @@
component.parseSettingId = function parseSettingId( settingId ) {
var parsed = {}, idParts;
idParts = settingId.replace( /]/g, '' ).split( '[' );
if ( 'post' !== idParts[0] && 'postmeta' !== idParts[0] ) {
return null;
}
parsed.settingType = idParts[0];
if ( 'post' === parsed.settingType && 3 !== idParts.length || 'postmeta' === parsed.settingType && 4 !== idParts.length ) {
return null;
}
parsed.settingType = idParts.shift();

parsed.postType = idParts[1];
parsed.postType = idParts.shift();
if ( ! parsed.postType ) {
return null;
}

parsed.postId = parseInt( idParts[2], 10 );
if ( isNaN( parsed.postId ) || parsed.postId <= 0 ) {
parsed.postId = parseInt( idParts.shift(), 10 );
if ( ! parsed.postId || isNaN( parsed.postId ) || parsed.postId <= 0 ) {
return null;
}

if ( 'postmeta' === parsed.settingType ) {
parsed.metaKey = idParts[3];
parsed.metaKey = idParts.shift();
if ( ! parsed.metaKey ) {
return null;
}
} else if ( 'post_terms' === parsed.settingType ) {
parsed.taxonomy = idParts.shift();
if ( ! parsed.taxonomy ) {
return null;
}
} else if ( 'post' !== parsed.settingType ) {
return null;
}

if ( 0 !== idParts.length ) {
return null; // Too many ID parts.
}

return parsed;
};

Expand Down
39 changes: 30 additions & 9 deletions js/edit-post-preview-admin.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,8 @@ var EditPostPreviewAdmin = (function( $ ) {
wasMobile,
parentId,
menuOrder,
request;
request,
postFormat;

event.preventDefault();

Expand Down Expand Up @@ -75,9 +76,17 @@ var EditPostPreviewAdmin = (function( $ ) {
ping_status: $( '#ping_status' ).prop( 'checked' ) ? 'open' : 'closed',
post_author: parseInt( $( '#post_author_override' ).val(), 10 )
};
postSettingId = 'post[' + postType + '][' + postId + ']';
postSettingId = 'post[' + postType + '][' + String( postId ) + ']';
settings[ postSettingId ] = postSettingValue;

postFormat = $( '#post-formats-select input[name=post_format]:checked' ).val();
if ( '0' === postFormat ) {
postFormat = 'standard';
}
if ( postFormat ) {
settings[ 'post_terms[' + postType + '][' + String( postId ) + '][post_format]' ] = postFormat;
}

// Allow plugins to inject additional settings to preview.
wp.customize.trigger( 'settings-from-edit-post-screen', settings );

Expand All @@ -86,15 +95,15 @@ var EditPostPreviewAdmin = (function( $ ) {
sessionStorage.setItem( 'previewedCustomizePostSettings[' + postId + ']', JSON.stringify( settings ) );
wp.customize.Loader.open( component.data.customize_url );
wp.customize.Loader.settings.browser.mobile = wasMobile;
component.bindChangesFromCustomizer( postSettingId, editor );
component.bindChangesFromCustomizer( postId, postType, editor );
} else {
$btn.addClass( 'disabled' );
component.previewButtonSpinner.addClass( 'is-active is-active-preview' );
request = wp.ajax.post( 'customize_posts_update_changeset', {
customize_posts_update_changeset_nonce: component.data.customize_posts_update_changeset_nonce,
previewed_post: component.data.previewed_post,
customize_url: component.data.customize_url,
input_data: postSettingValue
settings: JSON.stringify( settings )
} );

request.fail( function( resp ) {
Expand All @@ -108,7 +117,7 @@ var EditPostPreviewAdmin = (function( $ ) {
request.done( function( resp ) {
wp.customize.Loader.open( resp.customize_url );
wp.customize.Loader.settings.browser.mobile = wasMobile;
component.bindChangesFromCustomizer( postSettingId, editor );
component.bindChangesFromCustomizer( postId, postType, editor );
} );

request.always( function() {
Expand All @@ -121,13 +130,17 @@ var EditPostPreviewAdmin = (function( $ ) {
/**
* Sync changes from the Customizer to the post input fields.
*
* @param {string} postSettingId post setting id.
* @param {object} editor Tinymce object.
* @param {int} postId - Post ID.
* @param {string} postType - Post type.
* @param {object} editor - Tinymce object.
* @return {void}
*/
component.bindChangesFromCustomizer = function( postSettingId, editor ) {
component.bindChangesFromCustomizer = function( postId, postType, editor ) {
var postSettingId, postFormatSettingId;
postSettingId = 'post[' + postType + '][' + String( postId ) + ']';
postFormatSettingId = 'post_terms[' + postType + '][' + String( postId ) + '][post_format]';
wp.customize.Loader.messenger.bind( 'customize-post-settings-data', function( data ) {
var settingParentId;
var settingParentId, postFormatRadioSelector;
if ( data[ postSettingId ] ) {
$( '#title' ).val( data[ postSettingId ].post_title ).trigger( 'change' );
if ( editor ) {
Expand All @@ -147,6 +160,14 @@ var EditPostPreviewAdmin = (function( $ ) {
$( '#new-post-slug' ).val( data[ postSettingId ].post_name );
$( '#editable-post-name, #editable-post-name-full' ).text( data[ postSettingId ].post_name );
}
if ( data[ postFormatSettingId ] ) {
if ( 'standard' === data[ postFormatSettingId ] ) {
postFormatRadioSelector = '#post-format-0';
} else {
postFormatRadioSelector = '#post-format-' + data[ postFormatSettingId ];
}
$( postFormatRadioSelector ).prop( 'checked', true ).trigger( 'change' );
}

// Let plugins handle updates.
wp.customize.trigger( 'settings-from-customizer', data );
Expand Down
12 changes: 5 additions & 7 deletions js/edit-post-preview-customize.js
Original file line number Diff line number Diff line change
Expand Up @@ -101,13 +101,11 @@ var EditPostPreviewCustomize = (function( $, api ) {
} );

// Start listening to changes to the post and postmeta.
api( 'post[' + component.data.previewed_post.post_type + '][' + component.data.previewed_post.ID + ']', function( setting ) {
setting.bind( function( data ) {
var settings = {};
settings[ setting.id ] = data;
component.sendSettingsToEditPostScreen( settings );
} );
} );
api.bind( 'change', function( setting ) {
var settings = {};
settings[ setting.id ] = setting.get();
component.sendSettingsToEditPostScreen( settings );
});

component.parentFrame.send( 'customize-post-preview-ready' );
};
Expand Down
44 changes: 26 additions & 18 deletions php/class-edit-post-preview.php
Original file line number Diff line number Diff line change
Expand Up @@ -227,9 +227,14 @@ public function update_post_changeset() {
} elseif ( empty( $_POST['customize_url'] ) ) {
status_header( 400 );
wp_send_json_error( 'missing_customize_url' );
} elseif ( empty( $_POST['input_data'] ) || ! is_array( $_POST['input_data'] ) ) {
} elseif ( empty( $_POST['settings'] ) ) {
status_header( 400 );
wp_send_json_error( 'missing_input_data' );
wp_send_json_error( 'missing_settings' );
}
$setting_values = json_decode( wp_unslash( $_POST['settings'] ), true );
if ( ! is_array( $setting_values ) ) {
status_header( 400 );
wp_send_json_error( 'invalid_settings' );
}

$previewed_post_id = intval( wp_unslash( $_POST['previewed_post'] ) );
Expand Down Expand Up @@ -293,25 +298,28 @@ public function update_post_changeset() {
*/
$wp_customize_posts = $wp_customize->posts;

$settings = $wp_customize_posts->get_settings( array( $previewed_post_id ) );
$setting = array_shift( $settings );
if ( ! did_action( 'customize_register' ) ) {
remove_action( 'customize_register', array( $wp_customize, 'register_controls' ) );
$wp_customize->register_controls(); // Due to race condition with themes that set customize_register priority to 10.
do_action( 'customize_register', $wp_customize );
}
if ( ! did_action( 'customize_posts_register_meta' ) ) {
$wp_customize_posts->register_meta();
}

if ( ! $setting ) {
status_header( 404 );
wp_send_json_error( 'setting_not_found' );
return;
} elseif ( ! $setting->check_capabilities() ) {
status_header( 403 );
wp_send_json_error( 'changeset_already_published' );
return;
$wp_customize->add_dynamic_settings( array_keys( $setting_values ) );

foreach ( $setting_values as $setting_id => $setting_value ) {
$setting = $wp_customize->get_setting( $setting_id );
if ( $setting instanceof WP_Customize_Post_Setting ) {
$setting_value = wp_array_slice_assoc(
array_merge( $setting->value(), $setting_value ),
array_keys( $setting->default )
);
}
$wp_customize->set_post_value( $setting_id, $setting_value );
}
$setting->preview();

// Note that save_changeset_post() will handle validation and sanitization.
$wp_customize->set_post_value( $setting->id, wp_array_slice_assoc(
array_merge( $setting->value(), wp_unslash( $_POST['input_data'] ) ),
array_keys( $setting->default )
) );
$response = $wp_customize->save_changeset_post();
if ( is_wp_error( $response ) ) {
wp_send_json_error( $response->get_error_code() );
Expand Down
81 changes: 81 additions & 0 deletions php/class-wp-customize-post-format-setting.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
<?php
/**
* Customize Post Format Setting class.
*
* @package WordPress
* @subpackage Customize
*/

/**
* Class WP_Customize_Post_Format_Setting
*/
class WP_Customize_Post_Format_Setting extends WP_Customize_Post_Terms_Setting {

/**
* WP_Customize_Post_Format_Setting constructor.
*
* @param WP_Customize_Manager $manager Manager.
* @param string $id Setting ID.
* @param array $args Setting args.
* @throws Exception If the ID is in an invalid format or the taxonomy is invalid.
*/
public function __construct( WP_Customize_Manager $manager, $id, $args = array() ) {
parent::__construct( $manager, $id, $args );
if ( 'post_format' !== $this->taxonomy ) {
throw new Exception( 'Expected taxonomy to be post_format' );
}
}

/**
* Sanitize the setting's value for use in JavaScript.
*
* @return string Post Format.
*/
public function js_value() {
$term_ids = $this->value();
$term_id = array_shift( $term_ids );
if ( empty( $term_id ) ) {
return 'standard';
}
$term = get_term( $term_id, $this->taxonomy );
if ( ! ( $term instanceof WP_Term ) ) {
return 'standard';
}
return str_replace( 'post-format-', '', $term->slug );
}

/**
* Sanitize (and validate) an input.
*
* @param string $format The value to sanitize.
* @return array|WP_Error|null Sanitized term IDs array or WP_Error if invalid (or null if not WP 4.6-alpha).
*/
public function sanitize( $format ) {
$has_setting_validation = method_exists( 'WP_Customize_Setting', 'validate' );

if ( ! in_array( $format, get_post_format_slugs() ) ) {
return $has_setting_validation ? new WP_Error( 'illegal_slug', __( 'Unrecognized post format slug.', 'customize-posts' ) ) : null;
}

$value = array();
if ( 'standard' !== $format ) {
$slug = 'post-format-' . $format;
$term = get_term_by( 'slug', $slug, $this->taxonomy );

// Make sure the post format term exists.
if ( $term instanceof WP_Term ) {
$value[] = $term->term_id;
} else {
$term = wp_insert_term( $slug, $this->taxonomy );
if ( is_wp_error( $term ) ) {
return $has_setting_validation ? $term : null;
}
$value[] = $term['term_id'];
}
}

$value = parent::sanitize( $value );

return $value;
}
}
Loading