mirror of
https://github.com/silverstripe/silverstripe-framework
synced 2024-10-22 14:05:37 +02:00
NEW Documentation for Versioned
This commit is contained in:
parent
45b2cbfddd
commit
34a2ce23d8
@ -31,4 +31,3 @@ Reference articles complement our auto-generated [API docs](http://api.silverstr
|
||||
* [TableListField](tablelistfield): View and delete records in the CMS
|
||||
* [Typography](typography): CSS file to enable WYSIWYG previews in the CMS
|
||||
* [urlvariabletools](urlvariabletools): Debug and maintenance switches
|
||||
* [Versioned](versioned): Extension for SiteTree and other classes to store old versions and provide "staging"
|
@ -1,17 +0,0 @@
|
||||
# Versioned
|
||||
|
||||
The Versioned class is a `[api:DataObject]` that adds versioning and staging capabilities to the objects.
|
||||
|
||||
## Trapping the publication event
|
||||
|
||||
Sometimes, you'll want to do something whenever a particular kind of page is published. This example sends an email
|
||||
whenever a blog entry has been published.
|
||||
|
||||
:::php
|
||||
class Page extends SiteTree {
|
||||
// ...
|
||||
public function onAfterPublish() {
|
||||
mail("sam@silverstripe.com", "Blog published", "The blog has been published");
|
||||
parent::onAfterPublish();
|
||||
}
|
||||
}
|
@ -30,7 +30,4 @@ It is where most documentation should live, and is the natural "second step" aft
|
||||
* [Testing](testing): Functional and Unit Testing with PHPUnit and SilverStripe's testing framework
|
||||
* [Developing Themes](theme-development): Package templates, images and CSS to a reusable theme
|
||||
* [Widgets](widgets): Small feature blocks which can be placed on a page by the CMS editor, also outlines how to create and add widgets
|
||||
|
||||
## Feedback
|
||||
|
||||
If you have a topic you would like covered in these section please ask for it on our [Bug Tracker](http://open.silverstripe.org)
|
||||
* [Versioning](versioning): Extension for SiteTree and other classes to store old versions and provide "staging"
|
173
docs/en/topics/versioning.md
Normal file
173
docs/en/topics/versioning.md
Normal file
@ -0,0 +1,173 @@
|
||||
# Versioning of Database Content
|
||||
|
||||
## Overview
|
||||
|
||||
Database content in SilverStripe can be "staged" before its publication,
|
||||
as well as track all changes through the lifetime of a database record.
|
||||
|
||||
It is most commonly applied to pages in the CMS (the `SiteTree` class).
|
||||
This means that draft content edited in the CMS can be different from published content
|
||||
shown to your website visitors.
|
||||
|
||||
The versioning happens automatically on read and write.
|
||||
If you are using the SilverStripe ORM to perform these operations,
|
||||
you don't need to alter your existing calls.
|
||||
|
||||
Versioning in SilverStripe is handled through the `[api:Versioned]` class.
|
||||
It's a `[api:DataExtension]`, which allow it to be applied to any `[api:DataObject]` subclass.
|
||||
|
||||
## Configuration
|
||||
|
||||
Adding versioned to your `DataObject` subclass works the same as any other extension.
|
||||
It accepts two or more arguments denoting the different "stages",
|
||||
which map to different database tables.
|
||||
|
||||
:::php
|
||||
// mysite/_config.php
|
||||
Object::add_extension('MyRecord', 'Versioned("Stage","Live")');
|
||||
|
||||
Note: The extension is automatically applied to `SiteTree` class.
|
||||
|
||||
## Database Structure
|
||||
|
||||
Depending on how many stages you configured, two or more new tables will be created for your records.
|
||||
Note that the "Stage" naming has a special meaning here, it will leave the original
|
||||
table name unchanged, rather than adding a suffix.
|
||||
|
||||
* `MyRecord` table: Contains staged data
|
||||
* `MyRecord_Live` table: Contains live data
|
||||
* `MyRecord_versions` table: Contains a version history (new record created on each save)
|
||||
|
||||
Similarly, any subclass you create on top of a versioned base
|
||||
will trigger the creation of additional tables, which are automatically joined as required:
|
||||
|
||||
* `MyRecordSubclass` table: Contains only staged data for subclass columns
|
||||
* `MyRecordSubclass_Live` table: Contains only live data for subclass columns
|
||||
* `MyRecordSubclass_versions` table: Contains only version history for subclass columns
|
||||
|
||||
## Usage
|
||||
|
||||
### Reading Versions
|
||||
|
||||
By default, all records are retrieved from the "Draft" stage (so the `MyRecord` table in our example).
|
||||
You can explicitly request a certain stage through various getters on the `Versioned` class.
|
||||
|
||||
:::php
|
||||
// Fetching multiple records
|
||||
$stageRecords = Versioned::get_by_stage('MyRecord', 'Stage');
|
||||
$liveRecords = Versioned::get_by_stage('MyRecord', 'Live');
|
||||
|
||||
// Fetching a single record
|
||||
$stageRecord = Versioned::get_one_by_stage('MyRecord', 'Stage')->byID(99);
|
||||
$liveRecord = Versioned::get_one_by_stage('MyRecord', 'Live')->byID(99);
|
||||
|
||||
### Historical Versions
|
||||
|
||||
The above commands will just retrieve the latest version of its respective stage for you,
|
||||
but not older versions stored in the `<class>_versions` tables.
|
||||
|
||||
:::php
|
||||
$historicalRecord = Versioned::get_version('MyRecord', <record-id>, <version-id>);
|
||||
|
||||
Caution: The record is retrieved as a `DataObject`, but saving back modifications
|
||||
via `write()` will create a new version, rather than modifying the existing one.
|
||||
|
||||
In order to get a list of all versions for a specific record,
|
||||
we need to generate specialized `[api:Versioned_Version]` objects,
|
||||
which expose the same database information as a `DataObject`,
|
||||
but also include information about when and how a record was published.
|
||||
|
||||
:::php
|
||||
$record = MyRecord::get()->byID(99); // stage doesn't matter here
|
||||
$versions = $record->allVersions();
|
||||
echo $versions->First()->Version; // instance of Versioned_Versoin
|
||||
|
||||
### Writing Versions and Changing Stages
|
||||
|
||||
The usual call to `DataObject->write()` will write to whatever stage is currently
|
||||
active, as defined by the `Versioned::current_stage()` global setting.
|
||||
Each call will automatically create a new version in the `<class>_versions` table.
|
||||
To avoid this, use `[writeWithoutVersion()](api:Versioned->writeWithoutVersion())` instead.
|
||||
|
||||
To move a saved version from one stage to another,
|
||||
call `[writeToStage(<stage>)](api:Versioned->writeToStage())` on the object.
|
||||
The process of moving a version to a different stage is also called "publishing",
|
||||
so we've created a shortcut for this: `publish(<from-stage>, <to-stage>)`.
|
||||
|
||||
:::php
|
||||
$record = Versioned::get_by_stage('MyRecord', 'Stage')->byID(99);
|
||||
$record->MyField = 'changed';
|
||||
// will update `MyRecord` table (assuming Versioned::current_stage() == 'Stage'),
|
||||
// and write a row to `MyRecord_versions`.
|
||||
$record->write();
|
||||
// will copy the saved record information to the `MyRecord_Live` table
|
||||
$record->publish('Stage', 'Live');
|
||||
|
||||
Similarly, an "unpublish" operation does the reverse, and removes a record
|
||||
from a specific stage.
|
||||
|
||||
:::php
|
||||
$record = MyRecord::get()->byID(99); // stage doesn't matter here
|
||||
// will remove the row from the `MyRecord_Live` table
|
||||
$record->deleteFromStage('Live');
|
||||
|
||||
### Forcing the Current Stage
|
||||
|
||||
The current stage is stored as global state on the object.
|
||||
It is usually modified by controllers, e.g. when a preview is initialized.
|
||||
But it can also be set and reset temporarily to force a specific operation
|
||||
to run on a certain stage.
|
||||
|
||||
:::php
|
||||
$origMode = Versioned::get_reading_mode(); // save current mode
|
||||
$obj = MyRecord::getComplexObjectRetrieval(); // returns 'Live' records
|
||||
Versioned::set_reading_mode('Stage'); // temporarily overwrite mode
|
||||
$obj = MyRecord::getComplexObjectRetrieval(); // returns 'Stage' records
|
||||
Versioned::set_reading_mode($origMode); // reset current mode
|
||||
|
||||
### Custom SQL
|
||||
|
||||
We generally discourage writing `Versioned` queries from scratch,
|
||||
due to the complexities involved through joining multiple tables
|
||||
across an inherited table scheme (see `[api:Versioned->augmentSQL()]`).
|
||||
If possible, try to stick to smaller modifications of the generated `DataList` objects.
|
||||
|
||||
Example: Get the first 10 live records, filtered by creation date:
|
||||
|
||||
:::php
|
||||
$records = Versioned::get_by_stage('MyRecord', 'Live')->limit(10)->sort('Created', 'ASC');
|
||||
|
||||
### Permissions
|
||||
|
||||
The `Versioned` extension doesn't provide any permissions on its own,
|
||||
but you can have a look at the `SiteTree` class for implementation samples,
|
||||
specifically `canPublish()` and `canDeleteFromStage()`.
|
||||
|
||||
### Page Specific Operations
|
||||
|
||||
Since the `Versioned` extension is primarily used for page objects,
|
||||
the underlying `SiteTree` class has some additional helpers.
|
||||
See the ["sitetree" reference](/reference/sitetree) for details.
|
||||
|
||||
### Templates Variables
|
||||
|
||||
In templates, you don't need to worry about this distinction.
|
||||
The `$Content` variable contain the published content by default,
|
||||
and only preview draft content if explicitly requested (e.g. by the "preview" feature in the CMS).
|
||||
If you want to force a specific stage, we recommend the `Controller->init()` method for this purpose.
|
||||
|
||||
## Recipes
|
||||
|
||||
### Trapping the publication event
|
||||
|
||||
Sometimes, you'll want to do something whenever a particular kind of page is published. This example sends an email
|
||||
whenever a blog entry has been published.
|
||||
|
||||
:::php
|
||||
class Page extends SiteTree {
|
||||
// ...
|
||||
public function onAfterPublish() {
|
||||
mail("sam@silverstripe.com", "Blog published", "The blog has been published");
|
||||
parent::onAfterPublish();
|
||||
}
|
||||
}
|
@ -1025,7 +1025,10 @@ class Versioned extends DataExtension {
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the specific version of the given id
|
||||
* Return the specific version of the given id.
|
||||
* Caution: The record is retrieved as a DataObject, but saving back modifications
|
||||
* via write() will create a new version, rather than modifying the existing one.
|
||||
*
|
||||
* @return DataObject
|
||||
*/
|
||||
static function get_version($class, $id, $version) {
|
||||
|
Loading…
Reference in New Issue
Block a user