Learn

Revisions

Save revisions of your content with every update

Revisions (added in v1.10) is a bit more complex on the inside than the standard Statamic feature. Instead of being tightly-coupled to the core, revisions was built in a way that allows anyone to extend it.

We made things this way because we knew that revisions would be a popular feature, and we know that there are hundreds of different systems that people will want to use for storing revisions. We’re a small team, and couldn’t possibly hope to support all of these different adapters, so instead we’re leaving that up to third-parties to do.

While there is no “default” implementation for revisions, we’ve included a local_revisions bundle (in _app/core/bundles/local_revisions) for a couple reasons: one, so people can start using it right away, but two, so people can also see an example implementation of how revisions works. We highly recommend perusing that file before building.

Local Revisions

Statamic being a flat-file system, its only natural that you can save your revisions to files. As mentioned above, Statamic comes bundled with one Revisions implementation, local_revisions.

This bundle will allow revisions of your content to be saved to a _storage folder in your root. This folder should get checked into your version control system if you have one.

To enable local revisions, add _revisions: local_revisions to your settings.yaml and make sure _storage/ exists and is writeable.

Workflow

When saving a page in the Control Panel, upon hitting publish, you will be prompted with a field to type in a description of the change. (This is comparable to a commit message when using a system like Git).

When viewing a page that already has at least one revision saved, you will see a View Revisions button. Clicking this will show a modal window that lists all the revisions for this file. You can select a revision to view it. At this time your page will be populated with the older values. The page will not be saved until you re-publish it. You can make changes or re-publish as-is.

Implementing your own Revisions Adapter

The Structure of an Implementation

Creating an implementation of revisions in its simplest form is an add-on with just an API file. Of course, you can still use the data storage objects, configuration files, and the other aspects of add-ons (core, tasks, hooks, etc.), but all you really need to use is the API.

The revisions core defines an interface that your API must implement in order to work correctly. This is the Interface_revisions interface, and you must declare that it’s being implemented in your class call:

class API_my_revisions extends API implements Interface_revisions
{

}

This interface contains twelve methods that must be defined for your implementation of revisions to work properly. You can view the actual interface file at _app/core/bundles/revisions/interface.revisions.php, the methods are all well-commented, but the following is an overview of the methods that are needed.

The Boolean Checks

The following methods should return either true or false.

  • isProperlyConfigured – should determine if this add-on/implementation has been properly configured, the included local_revisions bundle simply returns true because no configuration is needed, but this is where you should check for properly set API keys and such if that applies
  • isRevision – checks to see if a given revision for a given file
  • isLatestRevision – checks to see if a given revision is the most-recent revision for a given file
  • hasRevisions – checks to see if a given file has revisions associated with it

Data Retrieval

The following methods return information about a file or revision.

  • getRevisions – returns an array of revisions for a given file, this should be an array of arrays, each of which contain five elements:
    • revision – the revision identifier
    • message – the save message associated with this revision
    • timestamp – the timestamp of when the revision happened
    • author – the author that saved the revision
    • is_current – a boolean of whether this revision is currently being viewed
  • getRevision – returns the data (the content file’s raw text) for a given revision on a given file
  • getRevisionTimestamp – returns the timestamp for a given revision on a given file
  • getRevisionAuthor – returns the author of a given revision on a given file

Data Storage

The following methods store information about a file or revision.

  • saveRevision – stores the given content for a given file with the given save message; this method can also optionally accept a timestamp to attempt back-dating revisions, this feature doesn’t need to be supported, and if it isn’t possible should simple store the current time; this method is called each time the publish button is clicked and something has changed in the content
  • saveFirstRevision – stores the very first revision for a given file, this will happen when a piece of content is loaded and no revisions are yet associated with the content (usually during times when you implement revisions after content already exists)

Data Altering

The following methods alter or remove information about a file or revision.

  • deleteRevisions – deletes all revisions for a given file, this will be triggered when a file has been deleted from Statamic
  • moveFile – allows the implementation to account for a file that’s changing its slug, this method gets passed the old file (with path) and the new file (with path)

This article was last updated on March 30th, 2016. Find an error? Please let us know!