-
-
Notifications
You must be signed in to change notification settings - Fork 97
Versioning
We build this inside the phpcr-odm because versioning is a core feature of phpcr.
Versioning in PHPCR is described in JCR 2.0, Chapter 15. Versioning is an optional feature, meaning not all PHPCR implementations support it.
There is 2 levels: simpleVersionable and (full) versionable. Simple versioning consists of a linear verison history and the checkin/checkout possibility. Checking in a node creates a new version and makes the node readonly. You need to check it out again to write to it (or just do a checkpoint to do both in one call). Full versioning additionally has non-linear versioning (which we won't provide any code for in phpcr-odm) and version labels. For each node, you can add labels to version, but one label string may only occur once per version history (meaning if you want to label another version, you need to remove the label from the first version before you add the label).
Version names are generated by PHPCR and can not be controlled by the client application. There is no concept of commit messages for PHPCR. We decided to not build something like that into the core of the ODM versioning system to avoid unnecessary overhead if the user does not need it. It is however easily doable with the allPredecessors parameters on a field
The admin bundle is supposed to support versions soon. See https://github.com/sonata-project/SonataDoctrinePhpcrAdminBundle/issues/12
We don't want to replicate the complete Version API (VersionManager, VersionHistory and Version). For the full power, the user will need to get the underlying session and interact with the VersionManager directly. However, some glue methods for the most common operations will be provided.
- Create versions: checkpoint/checkin/checkout($document)
- Get list of old versions
- Get document from old version
- Restore old version
- Remove old version
- later - once jackalope implements labels Support labels (full versioning only)
PHPCR-ODM must remain usable with repositories that don't support the Versioning capability, but versioning annotations and operations will not be supported.
@Document => versioningType=none/simple/full
Nice-to-have:
- @Document => checkpoint=manual/auto to create a version on every change
- @Document => later atLabel= to load a document at a specified label (i.e. "draft" or "stable"). this makes sense in combination with find with an explicit document name. its however a redundant method other way to make findVersionByLabel
- Field: later @Version(label=) to hold another version of this document at a specific version. (yes, yet another redundant method)
-
Field: @Version(allPredecessors=true) to hold the whole version history of that field (the changelog usecase)(to specific, just use the document manager for this) - Fields: later @VersionName, @VersionCreated, @VersionLabels: the corresponding property of the version this documents represents
Most methods need a document as parameter. Some would work with just a path too - if you need to optimize performance, you might want to use PHPCR directly in those cases to avoid the overhead.
Change them to check on the versionable annotation of the document instead of just adding mix:versionable. Support simpleVersionable too.
/**
* Check in $document, that is create a new version and mark it as read only
*/
checkin($document)
/**
* Check out $document, make it writable
*/
checkout($document)
/**
* Do a checkin operation followed immediatly by a checkout operation.
*
* A new version is created and the writable document stays in checked out
* state
*/
public function checkpoint($document)
Contrary to translations, getting an old version does not change the document representing the current version. An old version can't be modified and can't be persisted. (Except with the special restoreVersion method.) What you get is a detached instance of the document which is ignored by flush and can not be persisted.
/**
* Get the version history information for a document
*
* labels will be an empty array. TODO: implement labels once jackalope implements them
*
* @param $document the document of which to get the version history
* @param $limit an optional limit to only get the latest $limit informations
*
* @return array of <versionname> => array("labels" => <array of labels>, "created" => <DateTime>, "createdBy" => <username>), oldest version first
*/
public function getAllLinearVersions($document, $limit=-1)
/**
* Returns a read-only, detached document instance of the document at the
* specified path with the specified version name.
*
* @param null|string $className
* @param string $id
* @param string $versionname the version name as given by getLinearPredecessors
*
* @return the document or null if the document is not found
*
* @throws InvalidArgumentException if there is a document with $id but no version with $name
*/
public function findVersionByName($className, $id, $versionname)
public function getVersionInformation($doc, $name) (rather use the field annotations for VersionXX)
** later **
/** * Returns a read-only, detached document instance of the document at the * specified path with the specified version label. * * Only supported with documents that have versionable=full * TODO: implement once jackalope supports label */ public function findVersionByLabel($doc, $name)
Current DocumentManager has a method restore($version, $document, $removeExisting)
.
We suggest renaming it to restoreVersion to make the naming consistent and making it more strict: use the version you got with findVersionByName.
/**
* Restore the head of the history for $document to the particular version
*
* @param $document the version of the document as retrieved by findVersionByName
* @param $removeExisting whether to replace the existing head or add a new version after the current
*/
public function restoreVersion($documentVersion, $removeExisting=false);
/**
* Delete the specified version to clean up the history.
*
* @param $documentVersion the version of the document as retrieved by findVersionByName
*/
public function deleteVersion($documentVersion);
later
/**
* Remove the label $label from the version of $doc that has that label.
*
* Note: this different from phpcr where you first need to retrieve the version with
* the label and then remove the label from it. PHPCR-ODM can do this automatically for you
*
* Only supported with documents that have versionable=full
*
* @param $label the label to remove
* @param $doc either a string denoting the path or the document itself
*/
removeLabel($label, $doc)
/**
* A version can have as many labels as you want, but per document version
* history, each label may only exist once.
*
* Only supported with documents that have versionable=full
*
* @param $label the label to add
* @param $doc either a string denoting the path or the document itself
* @param $name the version name (if not specified, the $doc must be a
* document and not a path. the version name of $doc is used)
* @param boolean $autoremove whether to remove the label from the version
* history or throw an error if it already exists
*/
addLabel($label, $doc, $name=null, $autoremove=true)