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

Commit

Permalink
Merge pull request #335 from xwp/feature/partial-schema-refactor
Browse files Browse the repository at this point in the history
Improve logic for determining when to do fallback refresh for post field partials
  • Loading branch information
westonruter authored Dec 21, 2016
2 parents 6c92473 + 576b8ce commit 369f831
Show file tree
Hide file tree
Showing 13 changed files with 193 additions and 58 deletions.
37 changes: 35 additions & 2 deletions js/customize-post-field-partial.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,6 @@
api.selectiveRefresh.partialConstructor.deferred.prototype.initialize.call( partial, id, args );

partial.addInstantPreviews();

// @todo If singular_only, and this is not the post singular post for this partial, then no refresh!
},

/**
Expand Down Expand Up @@ -123,6 +121,41 @@
return refreshPromise;
},

/**
* Handle fail to render partial.
*
* {@inheritdoc}
*
* @this {wp.customize.selectiveRefresh.partialConstructor.deferred}
* @returns {void}
*/
fallback: function postFieldPartialFallback() {
var partial = this, dependentSelector;

/*
* Skip invoking fallback behavior for partials on documents that lack matches for
* the fallback dependent selector. The default fallback dependent selector is
* essentially checking to see if a body_class or post_class exists in the document
* which references the given post. If the dependent selector fails to match any
* elements, then the selector dependency fails and the partial should not be added.
* Note that the dependent selector could have been used as a determiner for whether
* the partial was added in the first place. However, this would have meant that no
* selective refresh requests would have been spawned by the change, and this would
* have meant that any Backbone models for the WP-API would not have had the chance
* to get the rendered updates from the server.
*/
dependentSelector = partial.params.fallbackDependentSelector;
if ( ! dependentSelector ) {
dependentSelector = '.hentry.post-%d, body.page-id-%d, body.postid-%d';
}
dependentSelector = dependentSelector.replace( /%d/g, String( partial.params.post_id ) );
if ( 0 === $( dependentSelector ).length ) {
return;
}

api.selectiveRefresh.partialConstructor.deferred.prototype.fallback.call( partial );
},

/**
* @inheritdoc
*/
Expand Down
69 changes: 60 additions & 9 deletions js/customize-preview-featured-image.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,11 @@ var CustomizePreviewFeaturedImage = (function( api, $ ) {

var component = {
data: {
partialSelectorAttribute: '',
partialContainerInclusive: true
partialArgs: {
selector: '',
containerInclusive: true,
fallbackDependentSelector: ''
}
}
};

Expand Down Expand Up @@ -56,6 +59,37 @@ var CustomizePreviewFeaturedImage = (function( api, $ ) {
*/
component.FeaturedImagePartial = api.selectiveRefresh.partialConstructor.deferred.extend({

idPattern: /^postmeta\[(.+?)]\[(\d+)]\[_thumbnail_id]$/,

/**
* Initialize.
*
* @param {string} id Partial ID.
* @param {object} args Args.
* @param {object} args.params Params.
* @returns {void}
*/
initialize: function( id, args ) {
var partial = this, matches, postId, postType, params;
matches = id.match( partial.idPattern );
postType = matches[1];
postId = parseInt( matches[2], 10 );
params = _.extend(
{
post_id: postId,
post_type: postType,
selector: component.data.partialArgs.selector.replace( /%d/g, String( postId ) ),
settings: [ id ],
primarySetting: id,
containerInclusive: component.data.partialArgs.containerInclusive,
fallbackDependentSelector: component.data.partialArgs.fallbackDependentSelector
},
args ? args.params || {} : {}
);

api.selectiveRefresh.partialConstructor.deferred.prototype.initialize.call( partial, id, { params: params } );
},

/**
* Force fallback (full page refresh) behavior when the featured image is removed.
*
Expand Down Expand Up @@ -93,6 +127,27 @@ var CustomizePreviewFeaturedImage = (function( api, $ ) {
} else {
return api.selectiveRefresh.Partial.prototype.renderContent.call( partial, placement );
}
},

/**
* Handle fail to render partial.
*
* Skip performing fallback behavior if post does not appear on the current template.
*
* {@inheritdoc}
*
* @this {wp.customize.selectiveRefresh.partialConstructor.deferred}
* @returns {void}
*/
fallback: function postFieldPartialFallback() {
var partial = this, dependentSelector;

dependentSelector = partial.params.fallbackDependentSelector.replace( /%d/g, String( partial.params.post_id ) );
if ( 0 === $( dependentSelector ).length ) {
return;
}

api.selectiveRefresh.partialConstructor.deferred.prototype.fallback.call( partial );
}
});

Expand All @@ -103,22 +158,18 @@ var CustomizePreviewFeaturedImage = (function( api, $ ) {
* @returns {component.FeaturedImagePartial|null} New or existing featured image partial, or null if not relevant setting.
*/
component.ensurePartialForSetting = function ensurePartialForSetting( setting ) {
var ensuredPartial, partialId, postId, matches = setting.id.match( /^postmeta\[.+?]\[(\d+)]\[_thumbnail_id]$/ );
if ( ! matches ) {
var ensuredPartial, partialId;
if ( ! component.FeaturedImagePartial.prototype.idPattern.test( setting.id ) ) {
return null;
}
partialId = setting.id;
postId = parseInt( matches[1], 10 );
ensuredPartial = api.selectiveRefresh.partial( partialId );
if ( ensuredPartial ) {
return ensuredPartial;
}
ensuredPartial = new component.FeaturedImagePartial( partialId, {
params: {
selector: '[' + component.data.partialSelectorAttribute + '=' + String( postId ) + ']',
settings: [ setting.id ],
primarySetting: setting.id,
containerInclusive: component.data.partialContainerInclusive
settings: [ setting.id ]
}
} );
api.selectiveRefresh.partial.add( partialId, ensuredPartial );
Expand Down
37 changes: 20 additions & 17 deletions js/customize-preview-posts.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@

// Add the partials.
_.each( api.previewPosts.partialSchema( setting.id ), function( schema ) {
var partial, addPartial, matches, baseSelector;
var partial, matches, postId, postType, selectorBases;

matches = schema.id.match( idPattern );
if ( ! matches ) {
Expand All @@ -46,25 +46,28 @@
if ( api.selectiveRefresh.partial.has( schema.id ) ) {
return;
}
postType = matches[1];
postId = parseInt( matches[2], 10 );

if ( schema.params.selector ) {
if ( ! schema.params.bodySelector ) {
baseSelector = '.hentry.post-' + String( parseInt( matches[2], 10 ) ) + '.type-' + matches[1];

selectorBases = [
'.hentry.post-' + String( postId )
];
if ( 'page' === postType ) {
selectorBases.push( 'body.page.page-id-' + String( postId ) );
} else {
baseSelector = '.postid-' + String( parseInt( matches[2], 10 ) ) + '.single-' + matches[1];
selectorBases.push( 'body.postid-' + String( postId ) );
}
schema.params.selector = baseSelector + ' ' + schema.params.selector;

addPartial =
! schema.params.singularOnly && ! schema.params.archiveOnly ||
schema.params.singularOnly && api.previewPosts.data.isSingular ||
schema.params.archiveOnly && ! api.previewPosts.data.isSingular;
schema.params.selector = _.map( selectorBases, function( selectorBase ) {
var selector = selectorBase + ' ' + schema.params.selector;
selector = selector.replace( /%d/g, String( postId ) );
return selector;
} ).join( ', ' );

if ( addPartial ) {
partial = new api.selectiveRefresh.partialConstructor.post_field( schema.id, { params: schema.params } );
api.selectiveRefresh.partial.add( partial.id, partial );
addedPartials.push( partial );
}
partial = new api.selectiveRefresh.partialConstructor.post_field( schema.id, { params: schema.params } );
api.selectiveRefresh.partial.add( partial.id, partial );
addedPartials.push( partial );
} else {
partial = new api.selectiveRefresh.partialConstructor.post_field( schema.id, { params: schema.params } );

Expand All @@ -79,7 +82,7 @@
partial.refresh = function refreshWithoutSelector() {
var deferred = $.Deferred();
if ( this.params.fallbackRefresh ) {
api.selectiveRefresh.requestFullRefresh();
api.selectiveRefresh.requestFullRefresh(); // @todo Do partial.fallback()?
deferred.resolve();
} else {
deferred.reject();
Expand Down Expand Up @@ -209,7 +212,7 @@
} );
};

wp.customize.selectiveRefresh.bind( 'render-partials-response', api.previewPosts.handleRenderPartialsResponse );
api.selectiveRefresh.bind( 'render-partials-response', api.previewPosts.handleRenderPartialsResponse );
};

/**
Expand Down
18 changes: 15 additions & 3 deletions php/class-wp-customize-featured-image-controller.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,13 @@ class WP_Customize_Featured_Image_Controller extends WP_Customize_Postmeta_Contr
*/
const SELECTED_ATTRIBUTE = 'data-customize-featured-image-partial';

/**
* Selector for finding featured images.
*
* @var string
*/
const SELECTOR = '[data-customize-featured-image-partial="%d"]';

/**
* The container_inclusive param for the partials.
*
Expand Down Expand Up @@ -117,9 +124,14 @@ public function enqueue_customize_pane_scripts() {
public function enqueue_customize_preview_scripts() {
$handle = 'customize-preview-featured-image';
wp_enqueue_script( $handle );

// @todo These arguments should be configurable for featured image partials just as they are for post field partials.
$exports = array(
'partialSelectorAttribute' => self::SELECTED_ATTRIBUTE,
'partialContainerInclusive' => self::PARTIAL_CONTAINER_INCLUSIVE,
'partialArgs' => array(
'selector' => self::SELECTOR,
'fallbackDependentSelector' => '.hentry.post-%d, body.page-id-%d, body.postid-%d',
'containerInclusive' => self::PARTIAL_CONTAINER_INCLUSIVE,
),
);
wp_add_inline_script( $handle, sprintf( 'CustomizePreviewFeaturedImage.init( %s )', wp_json_encode( $exports ) ) );
}
Expand Down Expand Up @@ -281,7 +293,7 @@ public function filter_customize_dynamic_partial_args( $partial_args, $partial_i
$partial_args['settings'] = array( $setting_id );
$partial_args['primary_setting'] = $setting_id;
$partial_args['type'] = 'featured_image';
$partial_args['selector'] = '[' . self::SELECTED_ATTRIBUTE . '=' . $matches['post_id'] . ']';
$partial_args['selector'] = sprintf( self::SELECTOR, $matches['post_id'] );
$partial_args['container_inclusive'] = self::PARTIAL_CONTAINER_INCLUSIVE;
}
return $partial_args;
Expand Down
31 changes: 11 additions & 20 deletions php/class-wp-customize-posts-preview.php
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,6 @@ public function customize_preview_init() {
add_action( 'parse_query', array( $this, 'ensure_page_for_posts_preview' ), 5 );
add_filter( 'customize_dynamic_partial_args', array( $this, 'filter_customize_dynamic_partial_args' ), 10, 2 );
add_filter( 'customize_dynamic_partial_class', array( $this, 'filter_customize_dynamic_partial_class' ), 10, 3 );
add_filter( 'customize_posts_partial_schema', array( $this, 'filter_customize_posts_partial_schema' ) );
add_filter( 'the_posts', array( $this, 'filter_the_posts_to_tally_previewed_posts' ), 1000 );
add_filter( 'the_posts', array( $this, 'filter_the_posts_to_tally_orderby_keys' ), 10, 2 );
add_action( 'wp_footer', array( $this, 'export_preview_data' ), 10 );
Expand Down Expand Up @@ -1222,20 +1221,6 @@ function filter_customize_dynamic_partial_class( $partial_class, $partial_id, $p
return $partial_class;
}

/**
* Prevent fallback_refresh for select post fields.
*
* @todo There should be some more sophisticated logic for determining whether fallback_refresh is done.
*
* @param array $schema Schema.
* @return array Schema.
*/
function filter_customize_posts_partial_schema( $schema ) {
$schema['post_title']['fallback_refresh'] = false;
$schema['post_excerpt']['fallback_refresh'] = false;
return $schema;
}

/**
* Filters get_edit_post_link to short-circuits if post cannot be edited in Customizer.
*
Expand Down Expand Up @@ -1321,22 +1306,19 @@ public function get_post_field_partial_schema( $field_id = '' ) {
),
'post_excerpt' => array(
'selector' => '.entry-summary',
'fallback_refresh' => true,
),
'comment_status[comments-area]' => array(
'selector' => '.comments-area',
'body_selector' => true,
'singular_only' => true,
'container_inclusive' => true,
),
'comment_status[comments-link]' => array(
'selector' => '.comments-link',
'archive_only' => true,
'fallback_dependent_selector' => 'body.archive', // Only do fallback when on archives.
'container_inclusive' => true,
),
'ping_status' => array(
'selector' => '.comments-area',
'body_selector' => true,
'singular_only' => true,
'container_inclusive' => true,
),
'post_author[byline]' => array(
Expand All @@ -1359,6 +1341,15 @@ public function get_post_field_partial_schema( $field_id = '' ) {
*/
$schema = apply_filters( 'customize_posts_partial_schema', $schema );

$deprecated_keys = array( 'body_selector', 'archive_only', 'singular_only' );
foreach ( $schema as $_field_id => $_partial_args ) {
foreach ( $deprecated_keys as $deprecated_key ) {
if ( array_key_exists( $deprecated_key, $_partial_args ) ) {
_deprecated_argument( __FUNCTION__, '0.8.5', sprintf( __( 'The %s param has been removed from the partial schema. Consider fallback_dependent_selector if needed.', 'customize-posts' ), $deprecated_key ) );
}
}
}

// Return specific schema based on the field_id & placement.
if ( ! empty( $field_id ) ) {
if ( isset( $schema[ $field_id ] ) ) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ public function filter_partial_schema( $schema ) {

$schema['post_author[biography]'] = array(
'selector' => '#author-info',
'singular_only' => true,
'fallback_dependent_selector' => 'body.singular',
'container_inclusive' => true,
'render_callback' => array( $this, 'biography_render_callback' ),
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ public function add_support() {
public function filter_partial_schema( $schema ) {
$schema['post_author[biography]'] = array(
'selector' => '.author-info',
'singular_only' => true,
'fallback_dependent_selector' => 'body.singular',
'container_inclusive' => true,
'render_callback' => array( $this, 'biography_render_callback' ),
);
Expand Down
Loading

0 comments on commit 369f831

Please sign in to comment.