Versioned
class Versioned extends DataExtension implements TemplateGlobalProvider, Resettable
The Versioned extension allows your DataObjects to have several versions, allowing you to rollback changes and view history. An example of this is the pages used in the CMS.
Note: This extension relies on the object also having the {see Ownership} extension applied.
Constants
DEFAULT_MODE |
The default reading mode |
STAGEDVERSIONED |
Constructor arg to specify that staging is active on this record. 'Staging' implies that 'Versioning' is also enabled. |
VERSIONED |
Constructor arg to specify that versioning only is active on this record. |
LIVE |
The Public stage. |
DRAFT |
The draft (default) stage |
MIGRATING_VERSION |
Field used to hold the migrating version |
NEXT_WRITE_WITHOUT_VERSIONED |
Field used to hold flag indicating the next write should be without a new version |
DELETE_WRITES_VERSION_DISABLED |
Prevents delete() from creating a _Versions record (in case this must be deferred) Best used with suppressDeleteVersion() |
Config options
draft_site_secured | bool | Default config for $is_draft_site_secured | |
non_virtual_fields | array | Ensure versioned page doesn't attempt to virtualise these non-db fields | |
casting | array | Ensure versioned records cast extra fields properly | |
db | array | ||
prepopulate_versionnumber_cache | boolean | Used to enable or disable the prepopulation of the version number cache. | |
use_conditions_over_inner_joins | bool | Indicates whether augmentSQL operations should add subselects as WHERE conditions instead of INNER JOIN intersections. Performance of the INNER JOIN scales on the size of _Versions tables where as the condition scales on the number of records being returned from the base query. | |
versionableExtensions | array | An array of DataObject extensions that may require versioning for extra tables The array value is a set of suffixes to form these table names, assuming a preceding '_'. | |
non_live_permissions | array | Permissions necessary to view records outside of the live stage (e.g. archive / draft stage). | |
use_session | bool | Use PHP's session storage for the "reading mode" and "unsecuredDraftSite", instead of explicitly relying on the "stage" query parameter. |
Properties
DataObject|RecursivePublishable|Versioned | $owner | ||
int | $Version |
Methods
Construct a new Versioned object.
Called when this extension is added to a particular class
Temporarily modify the owner. The original owner is ensured to be restored
Clear the current owner, and restore extension to the state prior to the last setOwner()
Helper method to strip eval'ed arguments from a string that's passed to {@link DataObject::$extensions} or {@link Object::add_extension()}.
Augment the the SQLSelect that is created by the DataQuery
Update the database schema as required by this extension.
Augment a write-record request.
No description
No description
Define extra database fields
This function is used to provide modifications to the form used for front end forms. {@link DataObject->getFrontEndFields()}
This is used to provide modifications to the form actions used in the CMS. {@link DataObject->getCMSActions()}.
this function is used to provide modifications to the summary fields in CMS by the extension By default, the summaryField() of its owner will merge more fields defined in the extension's $extra_fields['summary_fields']
No description
Reset static configuration variables to their default values.
Amend freshly created DataQuery objects with versioned-specific information.
Get this record at a specific version
Updates query parameters of relations attached to versioned dataobjects
For lazy loaded fields requiring extra sql manipulation, ie versioning.
Perform a write without affecting the version table.
Check if next write is without version
Set if next write should be without version or not
Check if delete() should write _Version rows or not
Set if delete() should write _Version rows
If a write was skipped, then we need to ensure that we don't leave a migrateVersion() value lying around for the next write.
This function should return true if the current user can publish this record.
Check if the current user can delete this record from live
Determine if there are any additional restrictions on this object for the given reading version.
Determines canView permissions for the latest version of this object on a specific stage.
Determine if a class is supporting the Versioned extensions (e.g.
Check if a certain table has the 'Version' field.
No description
Determines if the current draft version is the same as live or rather, that there are no outstanding draft changes
Publishes this object to Live, but doesn't publish owned objects.
Removes the record from both live and stage
Removes this record from the live site
Determine if this object is published, and has any published owners.
Revert the draft changes: replace the draft content with the content on live
Move a database record from one stage to the other.
Get version migrated to
Set the migrating version.
Compare two stages to see if they're different.
No description
Return a list of all the versions available.
Compare two version, and return the diff between them.
Given a table and stage determine the table name.
Determine if the current user is able to set the given site stage / archive
Set the current reading mode.
Get the current reading mode.
Get the current reading stage.
Get the current archive date.
Get the current archive stage.
Set the reading stage.
Replace default mode.
Get default reading mode
Check if draft site should be secured.
Set if the draft site should be secured or not
Set the reading archive date.
Get a singleton instance of a class in the given stage.
Gets the current version number of a specific record.
Hook into {@link Hierarchy::prepopulateTreeDataCache}.
Pre-populate the cache for Versioned::get_versionnumber_by_stage() for a list of record IDs, for more efficient database querying. If $idList is null, then every record will be pre-cached.
Get a set of class instances by the given stage.
Delete this record from the given stage
Write the given record to the given stage.
Roll the draft version of this record to match the published record.
Recursively rollback draft to the given version. This will also rollback any owned objects at that point in time to the same date. Objects which didn't exist (or weren't attached) to the record at the target point in time will be "unlinked", which dis-associates the record without requiring a hard deletion.
Rollback draft to a given version
Return the latest version of the given record.
Returns whether the current record is the latest one.
Returns whether the current record's version is the current live/published version
Returns whether the current record's version is the current draft/modified version
Check if this record exists on live
Check if page doesn't exist on any stage, but used to be
Check if this record exists on the draft stage
Compares current draft with live version, and returns true if no draft version of this page exists but the page is still published (eg, after triggering "Delete from draft site" in the CMS).
Compares current draft with live version, and returns true if no live version exists, meaning the page was never published.
Compares current draft with live version, and returns true if these versions differ, meaning there have been unpublished changes to the draft site.
Return the equivalent of a DataList::create() call, querying the latest version of each record stored in the (class)_Versions tables.
Return the specific version of the given id.
Return a list of all versions for a given id.
No description
Return a piece of text to keep DataObject cache keys appropriately specific.
Returns an array of possible stages.
Called by SSViewer to get a list of global variables to expose to the template, the static method to call on this class to get the value for those variables, and the class to use for casting the returned value for use in a template
Check if this object has stages
Invoke a callback which may modify reading mode, but ensures this mode is restored after completion, without modifying global state.
Details
at line 330
__construct($mode = self::STAGEDVERSIONED)
Construct a new Versioned object.
in Extension at line 50
static
add_to_class(string $class, string $extensionClass, mixed $args = null)
Called when this extension is added to a particular class
in Extension at line 60
setOwner(object $owner)
Set the owner of this extension.
in Extension at line 74
mixed
withOwner(mixed $owner, callable $callback, array $args = [])
Temporarily modify the owner. The original owner is ensured to be restored
in Extension at line 87
clearOwner()
Clear the current owner, and restore extension to the state prior to the last setOwner()
in Extension at line 100
Object
getOwner()
Returns the owner of this extension.
in Extension at line 113
static string
get_classname_without_arguments(string $extensionStr)
Helper method to strip eval'ed arguments from a string that's passed to {@link DataObject::$extensions} or {@link Object::add_extension()}.
in DataExtension at line 19
static
unload_extra_statics($class, $extension)
in DataExtension at line 30
validate(ValidationResult $validationResult)
Hook for extension-specific validation.
at line 484
augmentSQL(SQLSelect $query, DataQuery $dataQuery = null)
Augment the the SQLSelect that is created by the DataQuery
See {see augmentLazyLoadFields} for lazy-loading applied prior to this.
at line 940
augmentDatabase()
Update the database schema as required by this extension.
When duplicating a table's structure, remember to duplicate the create options as well. See {@link Versioned->augmentDatabase} for an example.
at line 1282
augmentWrite(array $manipulation)
Augment a write-record request.
in DataExtension at line 63
onBeforeWrite()
at line 1371
onAfterWrite()
in DataExtension at line 71
onBeforeDelete()
at line 1905
onAfterDelete()
in DataExtension at line 79
requireDefaultRecords()
in DataExtension at line 83
populateDefaults()
in DataExtension at line 87
can($member)
in DataExtension at line 91
canEdit($member)
in DataExtension at line 95
canDelete($member)
in DataExtension at line 99
canCreate($member)
in DataExtension at line 114
array
extraStatics(string $class = null, string $extension = null)
Define extra database fields
Return a map where the keys are db, has_one, etc, and the values are additional fields/relations to be defined.
at line 2940
updateCMSFields(FieldList $fields)
in DataExtension at line 144
updateFrontEndFields(FieldList $fields)
This function is used to provide modifications to the form used for front end forms. {@link DataObject->getFrontEndFields()}
Caution: Use {@link FieldList->push()} to add fields.
in DataExtension at line 154
updateCMSActions(FieldList $actions)
This is used to provide modifications to the form actions used in the CMS. {@link DataObject->getCMSActions()}.
in DataExtension at line 166
updateSummaryFields(array $fields)
this function is used to provide modifications to the summary fields in CMS by the extension By default, the summaryField() of its owner will merge more fields defined in the extension's $extra_fields['summary_fields']
at line 2932
updateFieldLabels(array $labels)
at line 301
static
reset()
Reset static configuration variables to their default values.
at line 314
augmentDataQueryCreation(SQLSelect $query, DataQuery $dataQuery)
Amend freshly created DataQuery objects with versioned-specific information.
at line 356
Versioned|DataObject
getAtVersion(int|string|null $from)
Get this record at a specific version
at line 434
updateInheritableQueryParams(array $params)
Updates query parameters of relations attached to versioned dataobjects
at line 919
augmentLoadLazyFields(SQLSelect $query, DataQuery $dataQuery = null, DataObject $dataObject)
For lazy loaded fields requiring extra sql manipulation, ie versioning.
at line 1361
int
writeWithoutVersion()
Perform a write without affecting the version table.
at line 1381
bool
getNextWriteWithoutVersion()
Check if next write is without version
at line 1392
DataObject
setNextWriteWithoutVersion(bool $flag)
Set if next write should be without version or not
at line 1402
bool
getDeleteWritesVersion()
Check if delete() should write _Version rows or not
at line 1413
DataObject
setDeleteWritesVersion(bool $flag)
Set if delete() should write _Version rows
at line 1439
onAfterSkippedWrite()
If a write was skipped, then we need to ensure that we don't leave a migrateVersion() value lying around for the next write.
at line 1455
bool
canPublish(Member $member = null)
This function should return true if the current user can publish this record.
It can be overloaded to customise the security model for an application.
Denies permission if any of the following conditions is true: - canPublish() on any extension returns false - canEdit() returns false
at line 1487
mixed
canUnpublish(null $member = null)
Check if the current user can delete this record from live
at line 1520
bool
canArchive(Member $member = null)
Check if the current user is allowed to archive this record.
If extended, ensure that both canDelete and canUnpublish are extended also
at line 1562
bool
canRevertToLive(Member $member = null)
Check if the user can revert this record to live
at line 1600
bool
canRestoreToDraft(Member $member = null)
Check if the user can restore this record to draft
at line 1633
bool|null
canView(Member $member = null)
Extend permissions to include additional security for objects that are not published to live.
at line 1658
bool
canViewVersioned(Member $member = null)
Determine if there are any additional restrictions on this object for the given reading version.
Override this in a subclass to customise any additional effect that Versioned applies to canView.
This is expected to be called by canView, and thus is only responsible for denying access if the default canView would otherwise ALLOW access. Thus it should not be called in isolation as an authoritative permission check.
This has the following extension points: - canViewDraft is invoked if Mode = stage and Stage = stage - canViewArchived is invoked if Mode = archive
at line 1724
bool
canViewStage(string $stage = self::LIVE, Member $member = null)
Determines canView permissions for the latest version of this object on a specific stage.
Usually the stage is read from {@link Versioned::current_stage()}.
This method should be invoked by user code to check if a record is visible in the given stage.
This method should not be called via ->extend('canViewStage'), but rather should be overridden in the extended class.
at line 1743
boolean
canBeVersioned(string $class)
Determine if a class is supporting the Versioned extensions (e.g.
$table_Versions does exists).
at line 1757
boolean
hasVersionField(string $table)
Check if a certain table has the 'Version' field.
at line 1769
string
extendWithSuffix(string $table)
at line 1797
bool
latestPublished()
Determines if the current draft version is the same as live or rather, that there are no outstanding draft changes
at line 1814
doPublish()
deprecated
deprecated 4.0..5.0
at line 1827
bool
publishSingle()
Publishes this object to Live, but doesn't publish owned objects.
User code should call {see canPublish()} prior to invoking this method.
at line 1851
bool
doArchive()
Removes the record from both live and stage
User code should call {see canArchive()} prior to invoking this method.
at line 1877
bool
doUnpublish()
Removes this record from the live site
User code should call {see canUnpublish()} prior to invoking this method.
at line 1920
bool
hasPublishedOwners()
Determine if this object is published, and has any published owners.
If this is true, a warning should be shown before this is published.
Note: This method returns false if the object itself is unpublished, since owners are only considered on the same stage as the record itself.
at line 1938
bool
doRevertToLive()
Revert the draft changes: replace the draft content with the content on live
User code should call {see canRevertToLive()} prior to invoking this method.
at line 1950
onAfterRevertToLive()
deprecated
deprecated 1.2..2.0 This extension method is redundant and will be removed
at line 1957
publish($fromStage, $toStage, $createNewVersion = true)
deprecated
deprecated 4.0..5.0
at line 1972
copyVersionToStage(int|string|null $fromStage, string $toStage, bool $createNewVersion = true)
Move a database record from one stage to the other.
at line 1998
int|null
getMigratingVersion()
Get version migrated to
at line 2007
migrateVersion(string $version)
deprecated
deprecated 4.0...5.0
at line 2019
DataObject
setMigratingVersion(string $version)
Set the migrating version.
at line 2031
bool
stagesDiffer()
Compare two stages to see if they're different.
Only checks the version numbers, not the actual content.
at line 2054
ArrayList
Versions(string $filter = "", string $sort = "", string $limit = "", string $join = "", string $having = "")
at line 2084
ArrayList
allVersions(string $filter = "", string $sort = "", string $limit = "", string $join = "", string $having = "")
deprecated
deprecated 1.5.0 Will be removed in 2.0.0, please use Versions() instead
Return a list of all the versions available.
at line 2142
DataObject
compareVersions(string $from, string $to)
Compare two version, and return the diff between them.
at line 2176
string
stageTable(string $table, string $stage)
Given a table and stage determine the table name.
Note: Stages this asset does not exist in will default to the draft table.
at line 2193
static bool
can_choose_site_stage(HTTPRequest $request)
Determine if the current user is able to set the given site stage / archive
at line 2231
static
choose_site_stage(HTTPRequest $request)
Choose the stage the site is currently on.
If $_GET['stage'] is set, then it will use that stage, and store it in the session.
if $_GET['archiveDate'] is set, it will use that date, and store it in the session.
If neither of these are set, it checks the session, otherwise the stage is set to 'Live'.
at line 2283
static
set_reading_mode(string $mode)
Set the current reading mode.
at line 2293
static string
get_reading_mode()
Get the current reading mode.
at line 2303
static string
get_stage()
Get the current reading stage.
at line 2318
static string
current_archived_date()
Get the current archive date.
at line 2332
static string
current_archived_stage()
Get the current archive stage.
at line 2347
static
set_stage(string $stage)
Set the reading stage.
at line 2359
static
set_default_reading_mode(string $mode)
Replace default mode.
An non-default mode should be specified via querystring arguments.
at line 2369
static string
get_default_reading_mode()
Get default reading mode
at line 2380
static bool
get_draft_site_secured()
Check if draft site should be secured.
Can be turned off if draft site unauthenticated
at line 2394
static
set_draft_site_secured(bool $secured)
Set if the draft site should be secured or not
at line 2405
static
reading_archived_date(string $date, string $stage = self::DRAFT)
Set the reading archive date.
at line 2422
static DataObject
get_one_by_stage(string $class, string $stage, string $filter = '', boolean $cache = true, string $sort = '')
Get a singleton instance of a class in the given stage.
at line 2439
static int|null
get_versionnumber_by_stage(string $class, string $stage, int $id, bool $cache = true)
Gets the current version number of a specific record.
at line 2489
onPrepopulateTreeDataCache(DataList|array $recordList = null, array $options = [])
Hook into {@link Hierarchy::prepopulateTreeDataCache}.
at line 2506
static
prepopulate_versionnumber_cache(string $class, string $stage, array $idList = null)
Pre-populate the cache for Versioned::get_versionnumber_by_stage() for a list of record IDs, for more efficient database querying. If $idList is null, then every record will be pre-cached.
at line 2560
static DataList
get_by_stage(string $class, string $stage, string $filter = '', string $sort = '', string $join = '', int $limit = null, string $containerClass = DataList::class)
Get a set of class instances by the given stage.
at line 2582
deleteFromStage(string $stage)
Delete this record from the given stage
at line 2605
int
writeToStage(string $stage, boolean $forceInsert = false)
Write the given record to the given stage.
Note: If writing to live, this will write to stage as well.
at line 2641
doRollbackTo(int $version)
deprecated
deprecated 4.2..5.0 Use rollbackRecursive() instead
Roll the draft version of this record to match the published record.
Caution: Doesn't overwrite the object properties with the rolled back version.
{see doRevertToLive()} to reollback to live
at line 2653
onAfterRollback()
deprecated
deprecated 1.2..2.0 This extension method is redundant and will be removed
at line 2667
DataObject|Versioned
rollbackRecursive(int|string|null $version = null)
Recursively rollback draft to the given version. This will also rollback any owned objects at that point in time to the same date. Objects which didn't exist (or weren't attached) to the record at the target point in time will be "unlinked", which dis-associates the record without requiring a hard deletion.
at line 2694
rollbackSingle(int|string|null $version)
Rollback draft to a given version
at line 2717
static DataObject
get_latest_version(string $class, int $id)
Return the latest version of the given record.
at line 2738
boolean
isLatestVersion()
Returns whether the current record is the latest one.
at line 2755
bool
isLiveVersion()
Returns whether the current record's version is the current live/published version
at line 2771
bool
isLatestDraftVersion()
Returns whether the current record's version is the current draft/modified version
at line 2787
bool
isPublished()
Check if this record exists on live
at line 2808
bool
isArchived()
Check if page doesn't exist on any stage, but used to be
at line 2819
bool
isOnDraft()
Check if this record exists on the draft stage
at line 2839
bool
isOnLiveOnly()
Compares current draft with live version, and returns true if no draft version of this page exists but the page is still published (eg, after triggering "Delete from draft site" in the CMS).
at line 2850
bool
isOnDraftOnly()
Compares current draft with live version, and returns true if no live version exists, meaning the page was never published.
at line 2861
bool
isModifiedOnDraft()
Compares current draft with live version, and returns true if these versions differ, meaning there have been unpublished changes to the draft site.
at line 2877
static DataList
get_including_deleted(string $class, string $filter = "", string $sort = "")
Return the equivalent of a DataList::create() call, querying the latest version of each record stored in the (class)_Versions tables.
In particular, this will query deleted records as well as active ones.
at line 2900
static DataObject
get_version(string $class, int $id, int $version)
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.
at line 2920
static DataList
get_all_versions(string $class, int $id)
Return a list of all versions for a given id.
at line 2953
onBeforeDuplicate(DataObject $source, bool $doWrite)
Ensure version ID is reset to 0 on duplicate
at line 2958
flushCache()
at line 2969
string
cacheKeyComponent()
Return a piece of text to keep DataObject cache keys appropriately specific.
at line 2979
array
getVersionedStages()
Returns an array of possible stages.
at line 2988
static array
get_template_global_variables()
Called by SSViewer to get a list of global variables to expose to the template, the static method to call on this class to get the value for those variables, and the class to use for casting the returned value for use in a template
If the method to call is not included for a particular template variable, a method named the same as the template variable will be called
If the casting class is not specified for a particular template variable, ViewableData::$default_cast is used
The first letter of the template variable is case-insensitive. However the method name is always case sensitive.
at line 3000
bool
hasStages()
Check if this object has stages
at line 3014
static mixed
withVersionedMode(callable $callback)
Invoke a callback which may modify reading mode, but ensures this mode is restored after completion, without modifying global state.
The desired reading mode should be set by the callback directly
at line 3030
Member|null
Author()
Get author of this record.
Note: Only works on records selected via Versions()
at line 3045
Member|null
Publisher()
Get publisher of this record.
Note: Only works on records selected via Versions()