Skip to content
This repository
Browse code

NEW Documentation for Versioned

  • Loading branch information...
commit 34a2ce23d8bf50b8ac19a4bac5a5a69e572c46d1 1 parent 45b2cbf
Ingo Schommer authored June 27, 2012
3  docs/en/reference/index.md
Source Rendered
@@ -30,5 +30,4 @@ Reference articles complement our auto-generated [API docs](http://api.silverstr
30 30
 * [TableField](tablefield): Add and edit records with inline edits in this form field
31 31
 * [TableListField](tablelistfield): View and delete records in the CMS
32 32
 * [Typography](typography): CSS file to enable WYSIWYG previews in the CMS
33  
-* [urlvariabletools](urlvariabletools): Debug and maintenance switches
34  
-* [Versioned](versioned): Extension for SiteTree and other classes to store old versions and provide "staging"
  33
+* [urlvariabletools](urlvariabletools): Debug and maintenance switches
17  docs/en/reference/versioned.md
Source Rendered
... ...
@@ -1,17 +0,0 @@
1  
-# Versioned
2  
-
3  
-The Versioned class is a `[api:DataObject]` that adds versioning and staging capabilities to the objects.
4  
-
5  
-## Trapping the publication event
6  
-
7  
-Sometimes, you'll want to do something whenever a particular kind of page is published.  This example sends an email
8  
-whenever a blog entry has been published.
9  
-
10  
-	:::php
11  
-	class Page extends SiteTree {
12  
-	  // ...
13  
-	  public function onAfterPublish() {
14  
-	    mail("sam@silverstripe.com", "Blog published", "The blog has been published");
15  
-	    parent::onAfterPublish();
16  
-	  }
17  
-	}
5  docs/en/topics/index.md
Source Rendered
@@ -30,7 +30,4 @@ It is where most documentation should live, and is the natural "second step" aft
30 30
  * [Testing](testing): Functional and Unit Testing with PHPUnit and SilverStripe's testing framework
31 31
  * [Developing Themes](theme-development): Package templates, images and CSS to a reusable theme
32 32
  * [Widgets](widgets): Small feature blocks which can be placed on a page by the CMS editor, also outlines how to create and add widgets
33  
-
34  
-## Feedback
35  
-
36  
-If you have a topic you would like covered in these section please ask for it on our [Bug Tracker](http://open.silverstripe.org)
  33
+ * [Versioning](versioning): Extension for SiteTree and other classes to store old versions and provide "staging"
173  docs/en/topics/versioning.md
Source Rendered
... ...
@@ -0,0 +1,173 @@
  1
+# Versioning of Database Content
  2
+
  3
+## Overview
  4
+
  5
+Database content in SilverStripe can be "staged" before its publication,
  6
+as well as track all changes through the lifetime of a database record.
  7
+
  8
+It is most commonly applied to pages in the CMS (the `SiteTree` class).
  9
+This means that draft content edited in the CMS can be different from published content
  10
+shown to your website visitors. 
  11
+
  12
+The versioning happens automatically on read and write.
  13
+If you are using the SilverStripe ORM to perform these operations,
  14
+you don't need to alter your existing calls.
  15
+
  16
+Versioning in SilverStripe is handled through the `[api:Versioned]` class.
  17
+It's a `[api:DataExtension]`, which allow it to be applied to any `[api:DataObject]` subclass.
  18
+
  19
+## Configuration
  20
+
  21
+Adding versioned to your `DataObject` subclass works the same as any other extension.
  22
+It accepts two or more arguments denoting the different "stages",
  23
+which map to different database tables.
  24
+
  25
+	:::php
  26
+	// mysite/_config.php
  27
+	Object::add_extension('MyRecord', 'Versioned("Stage","Live")');
  28
+
  29
+Note: The extension is automatically applied to `SiteTree` class.
  30
+
  31
+## Database Structure
  32
+
  33
+Depending on how many stages you configured, two or more new tables will be created for your records.
  34
+Note that the "Stage" naming has a special meaning here, it will leave the original
  35
+table name unchanged, rather than adding a suffix.
  36
+
  37
+ * `MyRecord` table: Contains staged data
  38
+ * `MyRecord_Live` table: Contains live data
  39
+ * `MyRecord_versions` table: Contains a version history (new record created on each save)
  40
+
  41
+Similarly, any subclass you create on top of a versioned base
  42
+will trigger the creation of additional tables, which are automatically joined as required:
  43
+
  44
+ * `MyRecordSubclass` table: Contains only staged data for subclass columns
  45
+ * `MyRecordSubclass_Live` table: Contains only live data for subclass columns
  46
+ * `MyRecordSubclass_versions` table: Contains only version history for subclass columns
  47
+
  48
+## Usage
  49
+
  50
+### Reading Versions
  51
+
  52
+By default, all records are retrieved from the "Draft" stage (so the `MyRecord` table in our example).
  53
+You can explicitly request a certain stage through various getters on the `Versioned` class.
  54
+
  55
+	:::php
  56
+	// Fetching multiple records
  57
+	$stageRecords = Versioned::get_by_stage('MyRecord', 'Stage');
  58
+	$liveRecords = Versioned::get_by_stage('MyRecord', 'Live');
  59
+
  60
+	// Fetching a single record
  61
+	$stageRecord = Versioned::get_one_by_stage('MyRecord', 'Stage')->byID(99);
  62
+	$liveRecord = Versioned::get_one_by_stage('MyRecord', 'Live')->byID(99);
  63
+
  64
+### Historical Versions
  65
+
  66
+The above commands will just retrieve the latest version of its respective stage for you,
  67
+but not older versions stored in the `<class>_versions` tables.
  68
+
  69
+	:::php
  70
+	$historicalRecord = Versioned::get_version('MyRecord', <record-id>, <version-id>);
  71
+
  72
+Caution: The record is retrieved as a `DataObject`, but saving back modifications
  73
+via `write()` will create a new version, rather than modifying the existing one.
  74
+
  75
+In order to get a list of all versions for a specific record,
  76
+we need to generate specialized `[api:Versioned_Version]` objects,
  77
+which expose the same database information as a `DataObject`,
  78
+but also include information about when and how a record was published.
  79
+	
  80
+	:::php
  81
+	$record = MyRecord::get()->byID(99); // stage doesn't matter here
  82
+	$versions = $record->allVersions();
  83
+	echo $versions->First()->Version; // instance of Versioned_Versoin
  84
+
  85
+### Writing Versions and Changing Stages
  86
+
  87
+The usual call to `DataObject->write()` will write to whatever stage is currently
  88
+active, as defined by the `Versioned::current_stage()` global setting.
  89
+Each call will automatically create a new version in the `<class>_versions` table.
  90
+To avoid this, use `[writeWithoutVersion()](api:Versioned->writeWithoutVersion())` instead.
  91
+
  92
+To move a saved version from one stage to another,
  93
+call `[writeToStage(<stage>)](api:Versioned->writeToStage())` on the object.
  94
+The process of moving a version to a different stage is also called "publishing",
  95
+so we've created a shortcut for this: `publish(<from-stage>, <to-stage>)`.
  96
+
  97
+	:::php
  98
+	$record = Versioned::get_by_stage('MyRecord', 'Stage')->byID(99);
  99
+	$record->MyField = 'changed';
  100
+	// will update `MyRecord` table (assuming Versioned::current_stage() == 'Stage'),
  101
+	// and write a row to `MyRecord_versions`.
  102
+	$record->write(); 
  103
+	// will copy the saved record information to the `MyRecord_Live` table
  104
+	$record->publish('Stage', 'Live');
  105
+
  106
+Similarly, an "unpublish" operation does the reverse, and removes a record
  107
+from a specific stage.
  108
+
  109
+	:::php
  110
+	$record = MyRecord::get()->byID(99); // stage doesn't matter here
  111
+	// will remove the row from the `MyRecord_Live` table
  112
+	$record->deleteFromStage('Live');
  113
+
  114
+### Forcing the Current Stage
  115
+
  116
+The current stage is stored as global state on the object.
  117
+It is usually modified by controllers, e.g. when a preview is initialized.
  118
+But it can also be set and reset temporarily to force a specific operation
  119
+to run on a certain stage.
  120
+
  121
+	:::php
  122
+	$origMode = Versioned::get_reading_mode(); // save current mode
  123
+	$obj = MyRecord::getComplexObjectRetrieval(); // returns 'Live' records
  124
+	Versioned::set_reading_mode('Stage'); // temporarily overwrite mode
  125
+	$obj = MyRecord::getComplexObjectRetrieval(); // returns 'Stage' records
  126
+	Versioned::set_reading_mode($origMode); // reset current mode
  127
+
  128
+### Custom SQL
  129
+
  130
+We generally discourage writing `Versioned` queries from scratch,
  131
+due to the complexities involved through joining multiple tables
  132
+across an inherited table scheme (see `[api:Versioned->augmentSQL()]`).
  133
+If possible, try to stick to smaller modifications of the generated `DataList` objects.
  134
+
  135
+Example: Get the first 10 live records, filtered by creation date:
  136
+
  137
+	:::php
  138
+	$records = Versioned::get_by_stage('MyRecord', 'Live')->limit(10)->sort('Created', 'ASC');
  139
+
  140
+### Permissions
  141
+
  142
+The `Versioned` extension doesn't provide any permissions on its own,
  143
+but you can have a look at the `SiteTree` class for implementation samples,
  144
+specifically `canPublish()` and `canDeleteFromStage()`.
  145
+
  146
+### Page Specific Operations
  147
+
  148
+Since the `Versioned` extension is primarily used for page objects,
  149
+the underlying `SiteTree` class has some additional helpers.
  150
+See the ["sitetree" reference](/reference/sitetree) for details.
  151
+
  152
+### Templates Variables
  153
+
  154
+In templates, you don't need to worry about this distinction.
  155
+The `$Content` variable contain the published content by default,
  156
+and only preview draft content if explicitly requested (e.g. by the "preview" feature in the CMS).
  157
+If you want to force a specific stage, we recommend the `Controller->init()` method for this purpose.
  158
+
  159
+## Recipes
  160
+
  161
+### Trapping the publication event
  162
+
  163
+Sometimes, you'll want to do something whenever a particular kind of page is published.  This example sends an email
  164
+whenever a blog entry has been published.
  165
+
  166
+	:::php
  167
+	class Page extends SiteTree {
  168
+	  // ...
  169
+	  public function onAfterPublish() {
  170
+	    mail("sam@silverstripe.com", "Blog published", "The blog has been published");
  171
+	    parent::onAfterPublish();
  172
+	  }
  173
+	}
5  model/Versioned.php
@@ -1025,7 +1025,10 @@ static function get_including_deleted($class, $filter = "", $sort = "") {
1025 1025
 	}
1026 1026
 	
1027 1027
 	/**
1028  
-	 * Return the specific version of the given id
  1028
+	 * Return the specific version of the given id.
  1029
+	 * Caution: The record is retrieved as a DataObject, but saving back modifications
  1030
+	 * via write() will create a new version, rather than modifying the existing one.
  1031
+	 * 
1029 1032
 	 * @return DataObject
1030 1033
 	 */
1031 1034
 	static function get_version($class, $id, $version) {

0 notes on commit 34a2ce2

Please sign in to comment.
Something went wrong with that request. Please try again.