Damian Mooyman 2017-08-22 16:43:02 +12:00
parent ecc619248b
commit 6b1dfddcb8
No known key found for this signature in database
GPG Key ID: 78B823A10DE27D1A

View File

@ -21,15 +21,15 @@ also track versioned history.
```php ```php
use SilverStripe\Versioned\Versioned; use SilverStripe\Versioned\Versioned;
use SilverStripe\ORM\DataObject; use SilverStripe\ORM\DataObject;
class MyStagedModel extends DataObject class MyStagedModel extends DataObject
{ {
private static $extensions = [ private static $extensions = [
Versioned::class Versioned::class
]; ];
} }
``` ```
Alternatively, staging can be disabled, so that only versioned changes are tracked for your model. This Alternatively, staging can be disabled, so that only versioned changes are tracked for your model. This
@ -37,14 +37,14 @@ can be specified by setting the constructor argument to "Versioned"
```php ```php
use SilverStripe\ORM\DataObject; use SilverStripe\ORM\DataObject;
class VersionedModel extends DataObject class VersionedModel extends DataObject
{ {
private static $extensions = [ private static $extensions = [
"SilverStripe\\ORM\\Versioning\\Versioned('Versioned')" "SilverStripe\\ORM\\Versioning\\Versioned('Versioned')"
]; ];
} }
``` ```
<div class="notice" markdown="1"> <div class="notice" markdown="1">
@ -57,6 +57,49 @@ Versioning only works if you are adding the extension to the base class. That is
of `DataObject`. Adding this extension to children of the base class will have unpredictable behaviour. of `DataObject`. Adding this extension to children of the base class will have unpredictable behaviour.
</div> </div>
## Versioned gridfield extension
By default the versioned module includes a `VersionedGridfieldDetailForm` that can extend gridfield
with versioning support for models.
You can enable this on a per-model basis using the following code:
```php
use SilverStripe\ORM\DataObject;
use SilverStripe\Versioned\Versioned;
class MyBanner extends DataObject {
private static $extensions = [
Versioned::class,
];
private static $versioned_gridfield_extensions = true;
}
```
This can be manually enabled for a single gridfield, alternatively, by setting the following option on the
GridFieldDetailForm component.
```php
use SilverStripe\CMS\Model\SiteTree;
use SilverStripe\Forms\GridField\GridField;
use SilverStripe\Forms\GridField\GridFieldConfig_RelationEditor;
use SilverStripe\Forms\GridField\GridFieldDetailForm;
use SilverStripe\Versioned\VersionedGridFieldItemRequest;
class Page extends SiteTree
{
public function getCMSFields()
{
$fields = parent::getCMSFields();
$config = GridFieldConfig_RelationEditor::create();
$config
->getComponentByType(GridFieldDetailForm::class)
->setItemRequestClass(VersionedGridFieldItemRequest::class);
$gridField = GridField::create('Items', 'Items', $this->Items(), $config);
$fields->addFieldToTab('Root.Items', $gridField);
return $fields;
}
}
```
## Database Structure ## Database Structure
Depending on whether staging is enabled, one or more new tables will be created for your records. `<class>_versions` Depending on whether staging is enabled, one or more new tables will be created for your records. `<class>_versions`
@ -87,13 +130,13 @@ By default, all records are retrieved from the "Draft" stage (so the `MyRecord`
explicitly request a certain stage through various getters on the `Versioned` class. explicitly request a certain stage through various getters on the `Versioned` class.
```php ```php
// Fetching multiple records // Fetching multiple records
$stageRecords = Versioned::get_by_stage('MyRecord', Versioned::DRAFT); $stageRecords = Versioned::get_by_stage('MyRecord', Versioned::DRAFT);
$liveRecords = Versioned::get_by_stage('MyRecord', Versioned::LIVE); $liveRecords = Versioned::get_by_stage('MyRecord', Versioned::LIVE);
// Fetching a single record // Fetching a single record
$stageRecord = Versioned::get_by_stage('MyRecord', Versioned::DRAFT)->byID(99); $stageRecord = Versioned::get_by_stage('MyRecord', Versioned::DRAFT)->byID(99);
$liveRecord = Versioned::get_by_stage('MyRecord', Versioned::LIVE)->byID(99); $liveRecord = Versioned::get_by_stage('MyRecord', Versioned::LIVE)->byID(99);
``` ```
### Historical Versions ### Historical Versions
@ -102,7 +145,7 @@ The above commands will just retrieve the latest version of its respective stage
in the `<class>_versions` tables. in the `<class>_versions` tables.
```php ```php
$historicalRecord = Versioned::get_version('MyRecord', <record-id>, <version-id>); $historicalRecord = Versioned::get_version('MyRecord', <record-id>, <version-id>);
``` ```
<div class="alert" markdown="1"> <div class="alert" markdown="1">
@ -115,9 +158,9 @@ objects, which expose the same database information as a `DataObject`, but also
a record was published. a record was published.
```php ```php
$record = MyRecord::get()->byID(99); // stage doesn't matter here $record = MyRecord::get()->byID(99); // stage doesn't matter here
$versions = $record->allVersions(); $versions = $record->allVersions();
echo $versions->First()->Version; // instance of Versioned_Version echo $versions->First()->Version; // instance of Versioned_Version
``` ```
### Writing Versions and Changing Stages ### Writing Versions and Changing Stages
@ -141,21 +184,21 @@ done via one of several ways:
See "DataObject ownership" for reference on dependant objects. See "DataObject ownership" for reference on dependant objects.
```php ```php
$record = Versioned::get_by_stage('MyRecord', Versioned::DRAFT)->byID(99); $record = Versioned::get_by_stage('MyRecord', Versioned::DRAFT)->byID(99);
$record->MyField = 'changed'; $record->MyField = 'changed';
// will update `MyRecord` table (assuming Versioned::current_stage() == 'Stage'), // will update `MyRecord` table (assuming Versioned::current_stage() == 'Stage'),
// and write a row to `MyRecord_versions`. // and write a row to `MyRecord_versions`.
$record->write(); $record->write();
// will copy the saved record information to the `MyRecord_Live` table // will copy the saved record information to the `MyRecord_Live` table
$record->publishRecursive(); $record->publishRecursive();
``` ```
Similarly, an "unpublish" operation does the reverse, and removes a record from a specific stage. Similarly, an "unpublish" operation does the reverse, and removes a record from a specific stage.
```php ```php
$record = MyRecord::get()->byID(99); // stage doesn't matter here $record = MyRecord::get()->byID(99); // stage doesn't matter here
// will remove the row from the `MyRecord_Live` table // will remove the row from the `MyRecord_Live` table
$record->deleteFromStage(Versioned::LIVE); $record->deleteFromStage(Versioned::LIVE);
``` ```
### Forcing the Current Stage ### Forcing the Current Stage
@ -164,11 +207,11 @@ The current stage is stored as global state on the object. It is usually modifie
is initialized. But it can also be set and reset temporarily to force a specific operation to run on a certain stage. is initialized. But it can also be set and reset temporarily to force a specific operation to run on a certain stage.
```php ```php
$origMode = Versioned::get_reading_mode(); // save current mode $origMode = Versioned::get_reading_mode(); // save current mode
$obj = MyRecord::getComplexObjectRetrieval(); // returns 'Live' records $obj = MyRecord::getComplexObjectRetrieval(); // returns 'Live' records
Versioned::set_reading_mode(Versioned::DRAFT); // temporarily overwrite mode Versioned::set_reading_mode(Versioned::DRAFT); // temporarily overwrite mode
$obj = MyRecord::getComplexObjectRetrieval(); // returns 'Stage' records $obj = MyRecord::getComplexObjectRetrieval(); // returns 'Stage' records
Versioned::set_reading_mode($origMode); // reset current mode Versioned::set_reading_mode($origMode); // reset current mode
``` ```
### DataObject ownership ### DataObject ownership
@ -191,21 +234,21 @@ without requiring any custom code.
```php ```php
use SilverStripe\Versioned\Versioned; use SilverStripe\Versioned\Versioned;
use SilverStripe\Assets\Image; use SilverStripe\Assets\Image;
use Page; use Page;
class MyPage extends Page class MyPage extends Page
{ {
private static $has_many = [ private static $has_many = [
'Banners' => Banner::class 'Banners' => Banner::class
]; ];
private static $owns = [ private static $owns = [
'Banners' 'Banners'
]; ];
} }
class Banner extends Page class Banner extends Page
{ {
private static $extensions = [ private static $extensions = [
Versioned::class Versioned::class
]; ];
@ -216,8 +259,7 @@ without requiring any custom code.
private static $owns = [ private static $owns = [
'Image' 'Image'
]; ];
} }
``` ```
Note that ownership cannot be used with polymorphic relations. E.g. has_one to non-type specific `DataObject`. Note that ownership cannot be used with polymorphic relations. E.g. has_one to non-type specific `DataObject`.
@ -236,11 +278,11 @@ that can be used to traverse between each, and then by ensuring you configure bo
E.g. E.g.
```php ```php
use SilverStripe\Versioned\Versioned; use SilverStripe\Versioned\Versioned;
use SilverStripe\ORM\DataObject; use SilverStripe\ORM\DataObject;
class MyParent extends DataObject class MyParent extends DataObject
{ {
private static $extensions = [ private static $extensions = [
Versioned::class Versioned::class
]; ];
@ -251,9 +293,9 @@ E.g.
{ {
return MyChild::get(); return MyChild::get();
} }
} }
class MyChild extends DataObject class MyChild extends DataObject
{ {
private static $extensions = [ private static $extensions = [
Versioned::class Versioned::class
]; ];
@ -264,8 +306,7 @@ E.g.
{ {
return MyParent::get()->first(); return MyParent::get()->first();
} }
} }
``` ```
#### DataObject Ownership in HTML Content #### DataObject Ownership in HTML Content
@ -286,7 +327,7 @@ smaller modifications of the generated `DataList` objects.
Example: Get the first 10 live records, filtered by creation date: Example: Get the first 10 live records, filtered by creation date:
```php ```php
$records = Versioned::get_by_stage('MyRecord', Versioned::LIVE)->limit(10)->sort('Created', 'ASC'); $records = Versioned::get_by_stage('MyRecord', Versioned::LIVE)->limit(10)->sort('Created', 'ASC');
``` ```
### Permissions ### Permissions
@ -310,12 +351,12 @@ Versioned object visibility can be customised in one of the following ways by ed
E.g. E.g.
```php ```php
use SilverStripe\Versioned\Versioned; use SilverStripe\Versioned\Versioned;
use SilverStripe\Security\Permission; use SilverStripe\Security\Permission;
use SilverStripe\ORM\DataObject; use SilverStripe\ORM\DataObject;
class MyObject extends DataObject class MyObject extends DataObject
{ {
private static $extensions = [ private static $extensions = [
Versioned::class, Versioned::class,
]; ];
@ -332,8 +373,7 @@ E.g.
// Only admins can view non-live objects // Only admins can view non-live objects
return Permission::checkMember($member, 'ADMIN'); return Permission::checkMember($member, 'ADMIN');
} }
} }
``` ```
If you want to control permissions of an object in an extension, you can also use If you want to control permissions of an object in an extension, you can also use
@ -348,16 +388,16 @@ only be invoked if the object is in a non-published state.
E.g. E.g.
```php ```php
use SilverStripe\Security\Permission; use SilverStripe\Security\Permission;
use SilverStripe\ORM\DataExtension; use SilverStripe\ORM\DataExtension;
class MyObjectExtension extends DataExtension class MyObjectExtension extends DataExtension
{ {
public function canViewNonLive($member = null) public function canViewNonLive($member = null)
{ {
return Permission::check($member, 'DRAFT_STATUS'); return Permission::check($member, 'DRAFT_STATUS');
} }
} }
``` ```
If none of the above checks are overridden, visibility will be determined by the If none of the above checks are overridden, visibility will be determined by the
@ -366,17 +406,16 @@ permissions in the `TargetObject.non_live_permissions` config.
E.g. E.g.
```php ```php
use SilverStripe\Versioned\Versioned; use SilverStripe\Versioned\Versioned;
use SilverStripe\ORM\DataObject; use SilverStripe\ORM\DataObject;
class MyObject extends DataObject class MyObject extends DataObject
{ {
private static $extensions = [ private static $extensions = [
Versioned::class, Versioned::class,
]; ];
private static $non_live_permissions = ['ADMIN']; private static $non_live_permissions = ['ADMIN'];
} }
``` ```
Versioned applies no additional permissions to `canEdit` or `canCreate`, and such Versioned applies no additional permissions to `canEdit` or `canCreate`, and such
@ -395,11 +434,11 @@ to force a specific stage, we recommend the `Controller->init()` method for this
**mysite/code/MyController.php** **mysite/code/MyController.php**
```php ```php
public function init() public function init()
{ {
parent::init(); parent::init();
Versioned::set_stage(Versioned::DRAFT); Versioned::set_stage(Versioned::DRAFT);
} }
``` ```
### Controllers ### Controllers