This guide demonstrates how to integrate PublishPress Revisions with WP Document Revisions to enable scheduling of document revision publications.
While WP Document Revisions supports scheduling the initial publication of documents by setting a future publish date, it doesn’t natively support scheduling revisions. PublishPress Revisions fills this gap by providing workflow management and scheduled publishing for post revisions.
wpdr-publishpress-revisions.phpwp-content/mu-plugins/ directorymu-plugins directory doesn’t exist, create itAdd the compatibility code to your theme’s functions.php file. Note that this approach ties the integration to your active theme.
<?php
/**
* WP Document Revisions - PublishPress Revisions Compatibility
*
* This compatibility layer enables PublishPress Revisions to work seamlessly
* with WP Document Revisions, allowing scheduled publication of document revisions.
*
* @package WP_Document_Revisions
* @subpackage Compatibility
*/
/**
* Class to handle compatibility between WP Document Revisions and PublishPress Revisions.
*/
class WP_Document_Revisions_PublishPress_Compatibility {
/**
* Initialize the compatibility layer.
*/
public function __construct() {
add_action( 'plugins_loaded', array( $this, 'add_hooks' ) );
}
/**
* Add WordPress hooks when both plugins are active.
*/
public function add_hooks() {
// Only proceed if both WPDR and PublishPress Revisions are active.
if ( ! $this->is_wpdr_active() || ! $this->is_publishpress_revisions_active() ) {
return;
}
// Remove the revision log meta box for draft revisions.
add_action( 'document_edit', array( $this, 'remove_revision_log_metabox' ) );
// Modify the permalink for draft document revisions.
add_filter( 'document_permalink', array( $this, 'modify_permalink' ), 10, 2 );
// Fix attachment parent relationship when revisions are approved.
add_filter( 'document_serve_attachment', array( $this, 'serve_attachment' ), 10, 2 );
// Ensure preview links use the correct format for documents.
add_filter( 'revisionary_preview_link_type', array( $this, 'preview_link_type' ), 10, 2 );
}
/**
* Check if WP Document Revisions is active.
*
* @return bool True if WPDR is active.
*/
private function is_wpdr_active() {
return class_exists( 'WP_Document_Revisions' );
}
/**
* Check if PublishPress Revisions is active.
*
* @return bool True if PublishPress Revisions is active.
*/
private function is_publishpress_revisions_active() {
// Check for the main PublishPress Revisions class.
return defined( 'PUBLISHPRESS_REVISIONS_VERSION' ) || class_exists( 'PublishPress_Revisions' );
}
/**
* Check if a post is a document.
*
* @param WP_Post|int|null $post Post object or ID.
* @return bool True if the post is a document.
*/
private function is_document( $post = null ) {
global $wpdr;
if ( ! $wpdr ) {
return false;
}
return $wpdr->verify_post_type( $post );
}
/**
* Check if a post is a document revision (draft state).
*
* @param WP_Post|int|null $post Post object or ID.
* @return bool True if the post is a document revision.
*/
private function is_document_revision( $post = null ) {
if ( ! $this->is_document( $post ) ) {
return false;
}
$post = get_post( $post );
if ( ! $post ) {
return false;
}
return 'draft' === $post->post_status;
}
/**
* Remove the revision log meta box from document edit screens for draft revisions.
*
* Draft revisions managed by PublishPress don't need the standard revision log
* since they're handled through the PublishPress workflow.
*/
public function remove_revision_log_metabox() {
global $post;
if ( ! $this->is_document_revision( $post ) ) {
return;
}
remove_meta_box( 'revision-summary', 'document', 'normal' );
}
/**
* Modify the permalink for draft document revisions.
*
* This filter hook ensures the permalink is processed through WPDR's logic
* in the correct order when working with PublishPress Revisions. While this
* method doesn't modify the link directly (WPDR handles the actual permalink
* generation), hooking into this filter ensures compatibility with both plugins'
* permalink handling.
*
* Note: This hook can be extended in the future if custom permalink modifications
* are needed for draft revisions.
*
* @param string $link The document permalink.
* @param WP_Post $post The document post object.
* @return string The permalink (unmodified by this method).
*/
public function modify_permalink( $link, $post ) {
if ( ! $this->is_document_revision( $post ) ) {
return $link;
}
// WPDR's permalink logic handles the URL structure for draft revisions.
// This hook ensures compatibility with PublishPress Revisions workflow.
return $link;
}
/**
* Fix attachment parent when serving documents from approved revisions.
*
* When PublishPress approves a revision, the attachment initially has the
* revision post as its parent rather than the original document. This filter
* corrects the parent relationship.
*
* @param WP_Post $attach The attachment post object.
* @param int $rev_id The revision ID (unused but required by filter signature).
* @return WP_Post The attachment with corrected parent.
*/
public function serve_attachment( $attach, $rev_id ) {
// phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter.FoundAfterLastUsed
if ( ! $attach || ! is_object( $attach ) ) {
return $attach;
}
// Validate attachment parent ID before querying.
if ( ! is_numeric( $attach->post_parent ) || $attach->post_parent <= 0 ) {
return $attach;
}
// Check if the attachment's parent is a revision (has a parent itself).
global $wpdb;
// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
$parent = $wpdb->get_var(
$wpdb->prepare(
"SELECT post_parent FROM {$wpdb->posts} WHERE ID = %d",
$attach->post_parent
)
);
// If the attachment's parent has a parent (meaning it's a revision),
// update the attachment to point to the original document.
if ( $parent && (int) $parent > 0 ) {
$result = wp_update_post(
array(
'ID' => $attach->ID,
'post_parent' => $parent,
)
);
// Log error if update fails, but still return the attachment.
if ( is_wp_error( $result ) ) {
// phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_error_log
error_log( 'WPDR PublishPress Compatibility: Failed to update attachment parent - ' . $result->get_error_message() );
return $attach;
}
$attach->post_parent = $parent;
}
return $attach;
}
/**
* Ensure the preview link type for draft document revisions is ID-only.
*
* PublishPress Revisions supports different preview link formats. For documents,
* the ID-only format works best to avoid routing conflicts.
*
* @param string $preview_link The preview link type.
* @param WP_Post $post Post object.
* @return string The preview link type.
*/
public function preview_link_type( $preview_link, $post ) {
if ( ! $this->is_document_revision( $post ) ) {
return $preview_link;
}
return 'id_only';
}
}
// Initialize the compatibility layer.
new WP_Document_Revisions_PublishPress_Compatibility();
After installing both plugins and the compatibility code, configure PublishPress Revisions:
The integration maintains compatibility with WP Document Revisions’ native workflow while adding scheduling capabilities.
Viewing Unapproved Documents: The document list may not show the pending revision’s attachment until it’s approved. This is a limitation of how PublishPress Revisions handles attachments.
Multiple Pending Revisions: Be cautious when multiple revisions are pending for the same document. The attachment parent fix applies when serving documents, but the queue interface may not fully reflect all attachment states.
Revision Log Display: Draft revisions managed by PublishPress don’t appear in the standard WP Document Revisions revision log until approved.
Problem: Preview link shows a random document or the published version instead of the draft revision.
Solution: Ensure the Preview Link Type is set to “Revision ID only” in PublishPress Revisions settings, or verify the compatibility code is active.
Problem: After approving a revision, the document still serves the old file.
Solution: The serve_attachment filter in the compatibility code should handle this. Verify:
Problem: The revision log meta box appears on draft revision edit screens.
Solution: Verify:
Hook Timing: The compatibility code hooks into document_edit action, which fires after WP Document Revisions sets up its meta boxes, ensuring proper removal order.
Permalink Handling: Uses the document_permalink filter to maintain URL consistency for draft revisions.
Attachment Management: The document_serve_attachment filter ensures that when serving a document, the attachment correctly points to the original document post, not the revision post.
Preview Links: The revisionary_preview_link_type filter ensures document previews use ID-based URLs to avoid routing conflicts with WP Document Revisions’ rewrite rules.
The compatibility code uses these hooks:
| Hook | Type | Purpose |
|---|---|---|
plugins_loaded |
Action | Initialize compatibility checks |
document_edit |
Action | Remove revision log meta box |
document_permalink |
Filter | Modify draft revision permalinks |
document_serve_attachment |
Filter | Fix attachment parent relationships |
revisionary_preview_link_type |
Filter | Set preview link format |
If you prefer not to use PublishPress Revisions, consider these alternatives:
Custom Scheduling: Implement a lightweight solution using WordPress cron and custom post meta to store scheduled revision dates.
Edit Flow: Another workflow plugin that may provide similar functionality, though not specifically tested with WPDR.
Manual Workflow: Use workflow states and manual publishing at the scheduled time.
For issues with:
This integration guide and compatibility code were developed based on community feedback and testing by:
This compatibility code is provided under the same license as WP Document Revisions (GPL v3 or later).