ProDrafts is a commercial module for ProcessWire that enables you to maintain separate draft and live versions of any page.
You can make edits to a draft version of the page without affecting the live version until you are ready to publish your draft.
ProDrafts provides a comparison and diff tool so that you can compare draft values to live values and view a diff for text changes. Furthermore, you can preview both the draft and live versions on the front-end of your site (see ProDrafts in action).
ProDrafts provides automatic save capability, ensuring that your work is never lost, even if you step away from the computer or otherwise forget to save. Edits are automatically saved to a draft of your page.
ProDrafts provides live preview, enabling you to edit and see your front-end output at the same time, side-by-side (watch how live preview works).
ProDrafts does all of this without you having to do anything other than install it. You might notice there are a lot of documentation topics below, but make no mistake, ProDrafts may be the easiest-to-use, most plug-and-play module you've installed, and it starts working immediately without you having to read any of this, if you don't want to.
Agency edition also available.
Table of contents
- Table of contents
- Requirements
- How to install
- ProDrafts in action
- Using Drafts
- Automatic save
- Live preview
- Access control
- Terms and Conditions
- ProDrafts API
- Introduction
- Finding all pages that have a draft
- Determining if a page has a draft version available
- Getting the draft version of a page (or creating one)
- Getting the live version of a page
- Determining if a given page is a draft version or a live version
- Determining whether drafts are allowed for a page
- Getting a list of changes in the draft
- Manipulating drafts
- Saving a draft
- Publishing a draft
- Deleting/abandoning a draft
Requirements
ProDrafts requires ProcessWire 2.7.0 or newer (3.x or newer preferred).
How to install
Unzip the ProDrafts[version].zip file and place the files in: /site/modules/ProDrafts/
In the ProcessWire admin, go to Modules > Refresh. Then go to Modules > Site and click "Install" next to ProDrafts.
Next you will see the ProDrafts configuration screen. Enable ProDrafts for all pages, or choose which templates you want to enable it for. From here you can also enable automatic save if you'd like (we do). Click "submit" to save your settings.
That's all!
ProDrafts in action
Much of what ProDrafts does is in the background, but there are a few notable changes you'll notice once ProDrafts is installed.
Drafts manager
You now have a Pages > Drafts menu item that goes to your drafts manager. From here you can review pending drafts, compare and view them, publish or abandon them, individually or in groups. All of the action links open in a modal window. To instead open in a new window/tab, long click the action link, holding down the mouse button till the new window/tab opens.
Page draft indicators and notification
When editing a page, you'll see a small paperclip icon in the top right corner of any finds that contain draft changes. If you have automatic save enabled, these will appear automatically as you make changes to your document. When automatic save is running, you'll see it momentarily change to a spinner.
When editing a page that is a draft, you'll see a notification at the top providing a few draft actions. Clicking any of those actions (other than the "abandon" action) opens a modal window. To open instead in a new window/tab, long-click the link, holding down the mouse button till the new window/tab opens.
Here's what the edit draft notification looks like in the Reno admin theme:
ProDrafts diff comparison example
ProDrafts module configuration screen
Live preview (preview while editing)
Using Drafts
Saving and publishing drafts
Edit any page using a template that supports drafts. For pages that are published, you should see "Publish" and "Save Draft" buttons. When you click the "Save Draft" button your changes are committed to a draft version of the page rather than the live version. When you click the Publish button, your draft changes are published to the live version of the page.
Make edits to the page and click the "Save Draft" button. After saving a draft, you should have a notification at the top of your screen giving you actions to view live and draft versions, compare differences or abandon (delete) the draft. The view and compare actions open in a modal window.
If you prefer to open those actions in a new window/tab, then perform a long-click instead, holding your mouse button down on the link until it opens a new window/tab.
Drafts and fields
Fields in your page editor that contain draft changes are accompanied by a paperclip icon in the top right corner of the field header. Click that icon to show differences for just that field.
Some fields on a page cannot be changed in a draft, and any changes will be published immediately, even if you click "Save Draft". These include the "name", "template" and "parent" system fields (seen on the "settings" tab). In addition, fields using a type of Repeater or PageTable are not currently supported for drafts (though support is planned). Any fields that can't be isolated in a draft are indicated with a warning icon in the top right corner of the field header.
Drafts manager
To see all pending drafts in the system, go to Pages > Drafts. From there you can perform batch publish/abandon operations, compare changes for any pending draft, or view draft and live versions in a modal window.
If you prefer to open the mentioned actions in a new window/tab rather than a modal window, then perform a long-click instead, holding your mouse button down on the link until it opens a new window/tab.
Considerations and limitations
What fields can be edited in a draft
ProDrafts works on any field that stores data in its dedicated ProcessWire field tables and/or the Page assets/files directory. This currently includes all Fieldtypes known to the author, except two: Repeater and PageTable (and fields based on them). If a field is not editable in a draft, ProDrafts makes the value non-editable unless you are saving to publish the page. Meaning, you can certainly have these fields and continue using ProDrafts, but the values of these fields are editable in the published version only. ProDrafts provides runtime warnings to keep you alert of these considerations when or if they appear.
The following native page properties are also not editable in drafts: URL, status, template, sortfield and parent. Most of these properties can affect the structure of a site outside of the individual page, which is why they are not supported in drafts.
Outside of the above considerations, and to the best of our knowledge, everything should be editable in a page draft.
ProDrafts and the front-end editor in ProcessWire 3.x
When a page has a draft, it may not be edited using the front-end editor unless you are viewing the front-end page as a draft. The front-end editor will simply be disabled. To enable, view the draft version of the page. You can do this by clicking the "View" link in the admin (assuming the page is already a draft), or by appending "?draft=1" to the URL of the page on the front-end.
ProDrafts and ListerPro inline page editing
If you are using ListerPro for page editing, note that ListerPro edits the live version of the page, not the draft version (if there is one). If an edit is made to a field on the live version of the page, and the draft does not contain edits to the same field, then the draft will also inherit the live edits. But if a change is made to the same field on the live version of the page that also has edits in the draft then the draft edits will override the live edits when published. When in doubt, use the compare tool before publishing drafts.
ProDrafts and other page editing tools or page edits from the API
Unless your API usage or alternate page editing module is specifically aware of ProDrafts, it will always be modifying the live version of the page, rather than the draft. If an edit is made to a field on the live version of the page, and the draft does not contain edits to the same field, then the draft will also inherit the live edits. But if a change is made to the same field on the live version of the page that also has edits in the draft, then the draft edits will override the live edits when published. When in doubt, use the compare tool before publishing drafts.
Automatic save
What is automatic save?
ProDrafts provides the optional capability to automatically save changes to the draft, before you have even clicked "save". This ensures that changes are not lost should you step away from the computer or otherwise forget to save the page.
Automatic save is supported for any pages that you have enabled to support drafts. When editing a page, if it is not already a draft, automatic save will create a draft to store the changes that it saves.
How does it work?
Automatic save looks for changes while you are editing, using one of two different methods: normal or relaxed. You can choose which method you prefer when configuring ProDrafts.
Normal auto-save method
The "normal" method monitors every key press, click and change that modifies data in the page editor. When it detects that you have made a change, it queues that change and waits for you to stop typing or clicking, etc. Once you stop for a second or two, it executes the automatic save silently in the background.
Relaxed auto-save method
The "relaxed" method only monitors change events as triggered by the browser. Meaning, if you are typing in a text field, the change event is only triggered when you de-focus (blur) the field. The relaxed method periodically (every 5 seconds) looks for fields that have had their change state triggered.
Note that when using CKEditor, a change event is triggered on every key press, making the normal and relaxed modes perform about the same when it comes to editing CKEditor fields.
Which method should you choose: normal or relaxed?
I would suggest starting with the normal method since it is going to be more thorough. If your page editor has a whole lot of fields and you notice any lag or slowdown, then you might consider switching to the relaxed method.
Auto-save exclusions
If for some reason you come across a field that does not behave nicely with auto-save, you have the option of disabling auto-save for that field from the ProDrafts module settings.
Live preview
ProDrafts provides live preview capabilities so that you can both edit your page and see the front-end output at the same time, side-by-side.
Enabling and accessing live preview
Live preview requires that "automatic save" mode is enabled. Following this, live preview can be enabled from the ProDrafts module configuration screen. Once enabled, live preview can be accessed by clicking the "Live Preview" link that appears at the top of your page editor. Live preview can also be accessed for a page by long-clicking (click and hold) the "edit" link that appears in the page list.
Live preview “normal” mode
In normal mode, live preview will attempt to update fields in your preview automatically without refreshing the preview. It can do this for most text-based fields in your preview automatically. For other fields, it will refresh the preview window. It is necessary for live preview to refresh the window since ProcessWire does not have any control over your front-end markup. Though you can provide hints to live preview that enable it to update without refresh.
Live preview hints in “normal” mode
For cases where live preview is unable to update without refresh, or for cases where you want to specifically tell it what to refresh, you can optionally provide hints (via class names) to live preview in your markup. Hints are simply class names in this format: pwpd-field
, where "field" is any field name. Note that "pwpd" is short for ProcessWire ProDrafts. Example:
<h1 class="pwpd-headline"><?=$page->headline?></h1>
The above example is simple, though also probably not necessary as live preview should be able to update a text field such as "headline" on its own. A more useful example might be in outputting a group of images. Lets say that your site already has this markup:
<ul class="my-photo-gallery"> <? foreach($page->photos as $photo): ?> <li> <img src="<?=$photo->url?>" alt="<?=$photo->description?>"> </li> <? endforeach; ?> </ul>
You can tell live preview that when a change is made to the field "photos", you want it to update the <ul>
element above by adding a pwpd-photos
class to it:
<ul class="my-photo-gallery pwpd-photos"> ... </ul>
The hint can be added to any containing element, it doesn't necessarily have to be the closest one. Just keep in mind it'll update everything within that element.
Note that you can also have multiple hints on any given containing element. If you've got a <div>
or <section>
(for example) that contains multiple fields you want to update at once, feel free to add multiple class name hints to it.
Live preview “refresh only” mode
The "refresh only" mode always refreshes the preview screen when changes are made. This may be what you want to use if you notice any rendering issues when the preview is updated in normal mode. For instance, "refresh only" mode might be necessary for layouts that depend heavily on javascript.
Access control
ProDrafts does not currently require any custom permissions, and instead uses ProcessWire's built-in page-edit permission, and optional page-publish permission.
Using the page-publish permission
By default, any user that has permission to edit a page also has permission to create or edit a draft of the page. If you have the page-publish
permission installed, then the user must also have that permission in order to publish a draft. This provides a nice upgrade for the page-publish permission over what is provided in the core, as users lacking page-publish permission cannot edit published pages. With ProDrafts installed, such users can now edit a draft of the published page, even if they can't publish the draft. This provides some very useful workflow potential for sites having multiple editors and access levels.
If you would like to use the page-publish permission, it may be installed by going to Access > Permissions > Add New, and choosing page-publish from the pre-defined optional permissions field. Note that once the page-publish permission is installed, it changes the access control behavior of your site, in that a user must have page-publish permission in order to publish a page, publish a draft, or edit an already published page. Users that lack page-publish permission can still create and edit the draft of a page.
Abandoning drafts and access control
When it comes to abandoning a draft (deleting rather than publishing) non-superusers can only abandon drafts that they created.
Terms and Conditions
ProDrafts is a commercially licensed and supported service provided by Ryan Dramer Design, LLC. You may not copy or distribute ProDrafts, except on site(s) you have registered it for with ProcessWire/Ryan Cramer Design, LLC. It is okay to make copies for use on staging or development servers specific to the site you registered for.
This service includes 1-year of support through the ProcessWire ProDrafts Support forum and/or email.
Disclaimer
In no event shall Ryan Cramer Design, LLC or ProcessWire be liable for any special, indirect, consequential, exemplary, or incidental damages whatsoever, including, without limitation, damage for loss of business profits, business interruption, loss of business information, loss of goodwill, or other pecuniary loss whether based in contract, tort, negligence, strict liability, or otherwise, arising out of the use or inability to use ProcessWire ProDrafts, even if Ryan Cramer Design, LLC / ProcessWire has been advised of the possibility of such damages.
Warranty, support, refunds
ProDrafts is provided "as-is" without warranty of any kind, either expressed or implied, including, but not limited to, the implied warranties of merchantability and fitness for a particular purpose. The entire risk as to the quality and performance of the program is with you. Should the program prove defective, you assume the cost of all necessary servicing, repair or correction. If within 7 days of purchase, you may request a full refund if you find the software does not suit your needs. Should you run into any trouble with ProDrafts, please email for support (ryan at this domain name) or visit the ProDrafts Support forum and we are here to help.
ProDrafts API
Introduction
ProDrafts is primarily an admin/UI tool, and our assumption is that many (most) users of ProDrafts likely won't use it outside of that context. But our experience with past Pro modules has been that there are also many users that like to utilize Pro module capabilities from the API side. Given that, we have given special attention to the ProDrafts public API.
The ProDrafts public API provides methods to load an manipulate drafts via hooks that it adds to the Page class. When working with ProDrafts from the API, any page may optionally have a single/separate draft version. The draft version of the page does not exist in the database. Instead, it is constructed at runtime by making a copy of the live page (in memory) and populating the changes from the draft into it. As a result, you should think of a draft page as a decorated copy of an original page, rather than as a separate page itself, and both the draft and live page share the same id.
Finding all pages that have a draft
In any $pages->find()
type selector, include status=64
as part of your selector, which corresponds to the constant Page::statusDraft
. It will return pages that have a draft present. For example:
$status = Page::statusDraft; // 64
$items = $pages->find("template=basic-page, status=$status");
Determining if a page has a draft version available
Use the hasDraft() method to determine if the page has a draft version available:
if($page->hasDraft()) {
// $page has a draft version available
}
Getting the draft version of a page (or creating one)
ProDrafts adds a $page->draftPage()
method, which returns the draft version of the page. If the page does not currently have a draft, then it will create a new one when the page returned by draftPage() is saved. If drafts are not allowed for $page, then it will return a NullPage (with id=0).
$draftPage = $page->draftPage(); if($draftPage->id) { // $draftPage is a draft version of $page }
if $page is already the draft version of the page, then it will simply return itself.
Note that the draft and live version of a page have the same id. The draft version of a page merely represents another copy of the same page in memory that has been populated with draft content.
Getting the live version of a page
If you have a draft version of a page and want the corresponding live version, use the livePage() method:
$livePage = $page->livePage();
if $page is already the live version of the page, then it will simply return itself.
Determining if a given page is a draft version or a live version
Use the $page->isDraft()
method to determine if a $page is a draft version or a live version:
if($page->isDraft()) {
// $page is a draft version
} else {
// $page is a live version
}
Note that the isDraft() method returns a ProDraft object if the page is a draft, and it returns boolean false if the page is not a draft version. The ProDraft object contains information about the draft, though it is not commonly needed for the public API.
$draft = $page->isDraft();
if($draft) {
// $page is a draft version, and $draft is a ProDraft object
} else {
// $page is a live version
}
Determining whether drafts are allowed for a page
ProDrafts lets you configure whether or not drafts are allowed for a given page. Use the $drafts->allowDraft($page)
method to make this determination:
if($drafts->allowDraft($page)) {
// drafts are allowed for $page
} else {
// drafts are not allowed for $page
}
Getting a list of changes in the draft
ProDrafts adds a $page->draftChanges()
method, which can be called from either the draft version or live version of the page (the result is the same). It is a regular PHP array containing a list of field names (strings) of fields that are different between the draft and live version of the page.
$changes = $page->draftChanges();
foreach($changes as $fieldName) {
echo "<p>$fieldName</p>";
}
Lets say that you want to list both the live value and the draft value together:
// we will assume $page is the live page $changes = $page->draftChanges(); $draftPage = $page->draftPage(); foreach($changes as $fieldName) { echo "<h2>Change: $fieldName</h2>"; echo "<h3>Live value</h3>" . $page->get($fieldName); echo "<h3>Draft value</h3>" . $draftPage->get($fieldName); }
Manipulating drafts
To manipulate the values on a draft page, simply set them as you would without ProDrafts. Just make sure that you are setting them to the draft version of the page, if that is where you intend to store them.
$p = $page->draftPage(); $p->summary = "Hello World"; $p->saveDraft();
Saving a draft
To save a draft version of a $page, use the saveDraft() method on the page. If $page is not the draft version of the page, then saveDraft() will load the draft version before committing the save.
$page->saveDraft();
Note: calling $page->save() or $pages->save($page) on a page that is already a draft version will have the same effect.
Publishing a draft
To publish the draft for a page, use publishDraft() method:
$page->publishDraft();
Deleting/abandoning a draft
To delete (abandon) the draft for a page, use the deleteDraft() method:
$page->deleteDraft();
For any of the above method calls, it doesn't matter if you call them on the live version or draft version of the page.
Agency edition also available.