diff --git a/src/wp-includes/js/wp-api.js b/src/wp-includes/js/wp-api.js index 31886d280b..856aa4c8b5 100644 --- a/src/wp-includes/js/wp-api.js +++ b/src/wp-includes/js/wp-api.js @@ -770,6 +770,36 @@ wp.api.WPApiBaseModel = Backbone.Model.extend( /** @lends WPApiBaseModel.prototype */ { + initialize: function( attributes, options ) { + + /** + * Determine if a model requires ?force=true to actually delete them. + */ + if ( + ! _.isEmpty( + _.filter( + this.endpoints, + function( endpoint ) { + return ( + + // Does the method support DELETE? + 'DELETE' === endpoint.methods[0] && + + // Exclude models that support trash (Post, Page). + ( + ! _.isUndefined( endpoint.args.force ) && + ! _.isUndefined( endpoint.args.force.description ) && + 'Whether to bypass trash and force deletion.' !== endpoint.args.force.description + ) + ); + } + ) + ) + ) { + this.requireForceForDelete = true; + } + }, + /** * Set nonce header before every Backbone sync. * @@ -1266,23 +1296,8 @@ // Include the array of route methods for easy reference. methods: modelRoute.route.methods, - initialize: function( attributes, options ) { - wp.api.WPApiBaseModel.prototype.initialize.call( this, attributes, options ); - - /** - * Posts and pages support trashing, other types don't support a trash - * and require that you pass ?force=true to actually delete them. - * - * @todo we should be getting trashability from the Schema, not hard coding types here. - */ - if ( - 'Posts' !== this.name && - 'Pages' !== this.name && - _.includes( this.methods, 'DELETE' ) - ) { - this.requireForceForDelete = true; - } - } + // Include the array of route endpoints for easy reference. + endpoints: modelRoute.route.endpoints } ); } else { @@ -1317,7 +1332,10 @@ name: modelClassName, // Include the array of route methods for easy reference. - methods: modelRoute.route.methods + methods: modelRoute.route.methods, + + // Include the array of route endpoints for easy reference. + endpoints: modelRoute.route.endpoints } ); } diff --git a/tests/qunit/wp-includes/js/wp-api.js b/tests/qunit/wp-includes/js/wp-api.js index e904ccaec8..5636dd8ea5 100644 --- a/tests/qunit/wp-includes/js/wp-api.js +++ b/tests/qunit/wp-includes/js/wp-api.js @@ -343,4 +343,42 @@ } ); }); + // Test that models have the correct requireForceForDelete setting. + var modelsThatNeedrequireForceForDelete = [ + { name: 'Category', expect: true }, + { name: 'Comment', expect: undefined }, + { name: 'Media', expect: undefined }, + { name: 'Page', expect: undefined }, + { name: 'PageRevision', expect: true }, + { name: 'Post', expect: undefined }, + { name: 'PostRevision', expect: true }, + { name: 'Status', expect: undefined }, + { name: 'Tag', expect: true }, + { name: 'Taxonomy', expect: undefined }, + { name: 'Type', expect: undefined }, + { name: 'User', expect: true } + ]; + + _.each( modelsThatNeedrequireForceForDelete, function( model ) { + QUnit.test( 'Test requireForceForDelete is correct for ' + model.name, function( assert ) { + var done = assert.async(); + assert.expect( 1 ); + wp.api.loadPromise.done( function() { + + // Instantiate the model. + var theModel = new wp.api.models[ model.name ](); + + // Verify the model's requireForceForDelete is set as expected. + assert.equal( + theModel.requireForceForDelete, + model.expect, + 'wp.api.models.' + model.name + '.requireForceForDelete should be ' + model.expect + '.' + ); + + // Trigger Qunit async completion. + done(); + } ); + } ); + } ); + } )( window.QUnit );