PHPDoc improvements for Hierarchy and Versioned

- Added missing @param and @method documentation
- Fixed incorrect PHPDoc @params and @returns
- Fixed wrapping width on many docblocks
- Added and/or improved method documentation when missing or confusing
- Fixed typos as found
- Removed references to 'Page' in Versioned documentation
This commit is contained in:
Nik Rolls 2014-12-02 01:20:09 +13:00 committed by Sam Minnee
parent 8ebdedf330
commit 9791426be6
2 changed files with 314 additions and 278 deletions

View File

@ -1,9 +1,14 @@
<?php
/**
* DataObjects that use the Hierarchy extension can be be organised as a hierarchy, with children and parents.
* The most obvious example of this is SiteTree.
* DataObjects that use the Hierarchy extension can be be organised as a hierarchy, with children and parents. The most
* obvious example of this is SiteTree.
*
* @package framework
* @subpackage model
*
* @property int ParentID
* @property DataObject owner
* @method DataObject Parent
*/
class Hierarchy extends DataExtension {
@ -11,30 +16,28 @@ class Hierarchy extends DataExtension {
protected $markingFilter;
/**
* @var Int
*/
/** @var int */
protected $_cache_numChildren;
/**
* The lower bounds for the amount of nodes to mark. If set, the logic will expand nodes until it reaches at least
* this number, and then stops. Root nodes will always show regardless of this settting. Further nodes can be
* lazy-loaded via ajax. This isn't a hard limit. Example: On a value of 10, with 20 root nodes, each having 30
* children, the actual node count will be 50 (all root nodes plus first expanded child).
*
* @config
* @var integer The lower bounds for the amount of nodes to mark. If set, the logic will expand
* nodes until it reaches at least this number, and then stops. Root nodes will always
* show regardless of this settting. Further nodes can be lazy-loaded via ajax.
* This isn't a hard limit. Example: On a value of 10, with 20 root nodes, each having
* 30 children, the actual node count will be 50 (all root nodes plus first expanded child).
* @var int
*/
private static $node_threshold_total = 50;
/**
* Limit on the maximum children a specific node can display. Serves as a hard limit to avoid exceeding available
* server resources in generating the tree, and browser resources in rendering it. Nodes with children exceeding
* this value typically won't display any children, although this is configurable through the $nodeCountCallback
* parameter in {@link getChildrenAsUL()}. "Root" nodes will always show all children, regardless of this setting.
*
* @config
* @var integer Limit on the maximum children a specific node can display.
* Serves as a hard limit to avoid exceeding available server resources
* in generating the tree, and browser resources in rendering it.
* Nodes with children exceeding this value typically won't display
* any children, although this is configurable through the $nodeCountCallback
* parameter in {@link getChildrenAsUL()}. "Root" nodes will always show
* all children, regardless of this setting.
* @var int
*/
private static $node_threshold_leaf = 250;
@ -46,6 +49,8 @@ class Hierarchy extends DataExtension {
/**
* Validate the owner object - check for existence of infinite loops.
*
* @param ValidationResult $validationResult
*/
public function validate(ValidationResult $validationResult) {
// The object is new, won't be looping.
@ -78,19 +83,21 @@ class Hierarchy extends DataExtension {
}
/**
* Returns the children of this DataObject as an XHTML UL. This will be called recursively on each child,
* so if they have children they will be displayed as a UL inside a LI.
* @param string $attributes Attributes to add to the UL.
* @param string|callable $titleEval PHP code to evaluate to start each child - this should include '<li>'
* @param string $extraArg Extra arguments that will be passed on to children, for if they overload this function.
* @param boolean $limitToMarked Display only marked children.
* @param string $childrenMethod The name of the method used to get children from each object
* @param boolean $rootCall Set to true for this first call, and then to false for calls inside the recursion. You
* should not change this.
* @param int $nodeCountThreshold See {@link self::$node_threshold_total}
* @param callable $nodeCountCallback Called with the node count, which gives the callback an opportunity
* to intercept the query. Useful e.g. to avoid excessive children listings
* (Arguments: $parent, $numChildren)
* Returns the children of this DataObject as an XHTML UL. This will be called recursively on each child, so if they
* have children they will be displayed as a UL inside a LI.
*
* @param string $attributes Attributes to add to the UL
* @param string|callable $titleEval PHP code to evaluate to start each child - this should include '<li>'
* @param string $extraArg Extra arguments that will be passed on to children, for if they
* overload this function
* @param bool $limitToMarked Display only marked children
* @param string $childrenMethod The name of the method used to get children from each object
* @param bool $rootCall Set to true for this first call, and then to false for calls inside
* the recursion. You should not change this.
* @param int $nodeCountThreshold See {@link self::$node_threshold_total}
* @param callable $nodeCountCallback Called with the node count, which gives the callback an opportunity to
* intercept the query. Useful e.g. to avoid excessive children listings
* (Arguments: $parent, $numChildren)
*
* @return string
*/
@ -175,11 +182,12 @@ class Hierarchy extends DataExtension {
/**
* Mark a segment of the tree, by calling mark().
* The method performs a breadth-first traversal until the number of nodes is more than minCount.
* This is used to get a limited number of tree nodes to show in the CMS initially.
*
* This method returns the number of nodes marked. After this method is called other methods
* can check isExpanded() and isMarked() on individual nodes.
* The method performs a breadth-first traversal until the number of nodes is more than minCount. This is used to
* get a limited number of tree nodes to show in the CMS initially.
*
* This method returns the number of nodes marked. After this method is called other methods can check
* {@link isExpanded()} and {@link isMarked()} on individual nodes.
*
* @param int $nodeCountThreshold See {@link getChildrenAsUL()}
* @return int The actual number of nodes marked.
@ -205,9 +213,10 @@ class Hierarchy extends DataExtension {
}
/**
* Filter the marking to only those object with $node->$parameterName = $parameterValue
* @param string $parameterName The parameter on each node to check when marking.
* @param mixed $parameterValue The value the parameter must be to be marked.
* Filter the marking to only those object with $node->$parameterName == $parameterValue
*
* @param string $parameterName The parameter on each node to check when marking.
* @param mixed $parameterValue The value the parameter must be to be marked.
*/
public function setMarkingFilter($parameterName, $parameterValue) {
$this->markingFilter = array(
@ -217,9 +226,10 @@ class Hierarchy extends DataExtension {
}
/**
* Filter the marking to only those where the function returns true.
* The node in question will be passed to the function.
* @param string $funcName The function name.
* Filter the marking to only those where the function returns true. The node in question will be passed to the
* function.
*
* @param string $funcName The name of the function to call
*/
public function setMarkingFilterFunction($funcName) {
$this->markingFilter = array(
@ -229,8 +239,9 @@ class Hierarchy extends DataExtension {
/**
* Returns true if the marking filter matches on the given node.
* @param DataObject $node Node to check.
* @return boolean
*
* @param DataObject $node Node to check
* @return bool
*/
public function markingFilterMatches($node) {
if(!$this->markingFilter) {
@ -257,7 +268,11 @@ class Hierarchy extends DataExtension {
/**
* Mark all children of the given node that match the marking filter.
* @param DataObject $node Parent node.
*
* @param DataObject $node Parent node
* @param mixed $context
* @param string $childrenMethod The name of the instance method to call to get the object's list of children
* @param string $numChildrenMethod The name of the instance method to call to count the object's children
* @return DataList
*/
public function markChildren($node, $context = null, $childrenMethod = "AllChildrenIncludingDeleted",
@ -288,8 +303,10 @@ class Hierarchy extends DataExtension {
}
/**
* Ensure marked nodes that have children are also marked expanded.
* Call this after marking but before iterating over the tree.
* Ensure marked nodes that have children are also marked expanded. Call this after marking but before iterating
* over the tree.
*
* @param string $numChildrenMethod The name of the instance method to call to count the object's children
*/
protected function markingFinished($numChildrenMethod = "numChildren") {
// Mark childless nodes as expanded.
@ -303,9 +320,10 @@ class Hierarchy extends DataExtension {
}
/**
* Return CSS classes of 'unexpanded', 'closed', both, or neither, as well as a
* 'jstree-*' state depending on the marking of this DataObject.
* Return CSS classes of 'unexpanded', 'closed', both, or neither, as well as a 'jstree-*' state depending on the
* marking of this DataObject.
*
* @param string $numChildrenMethod The name of the instance method to call to count the object's children
* @return string
*/
public function markingClasses($numChildrenMethod="numChildren") {
@ -327,8 +345,10 @@ class Hierarchy extends DataExtension {
/**
* Mark the children of the DataObject with the given ID.
* @param int $id ID of parent node.
* @param boolean $open If this is true, mark the parent node as opened.
*
* @param int $id ID of parent node
* @param bool $open If this is true, mark the parent node as opened
* @return bool
*/
public function markById($id, $open = false) {
if(isset($this->markedNodes[$id])) {
@ -344,6 +364,7 @@ class Hierarchy extends DataExtension {
/**
* Expose the given object in the tree, by marking this page and all it ancestors.
*
* @param DataObject $childObj
*/
public function markToExpose($childObj) {
@ -356,7 +377,9 @@ class Hierarchy extends DataExtension {
}
/**
* Return the IDs of all the marked nodes
* Return the IDs of all the marked nodes.
*
* @return array
*/
public function markedNodeIDs() {
return array_keys($this->markedNodes);
@ -364,7 +387,8 @@ class Hierarchy extends DataExtension {
/**
* Return an array of this page and its ancestors, ordered item -> root.
* @return array
*
* @return SiteTree[]
*/
public function parentStack() {
$p = $this->owner;
@ -378,20 +402,20 @@ class Hierarchy extends DataExtension {
}
/**
* True if this DataObject is marked.
* @var boolean
* Cache of DataObjects' marked statuses: [ClassName][ID] = bool
* @var array
*/
protected static $marked = array();
/**
* True if this DataObject is expanded.
* @var boolean
* Cache of DataObjects' expanded statuses: [ClassName][ID] = bool
* @var array
*/
protected static $expanded = array();
/**
* True if this DataObject is opened.
* @var boolean
* Cache of DataObjects' opened statuses: [ClassName][ID] = bool
* @var array
*/
protected static $treeOpened = array();
@ -430,7 +454,8 @@ class Hierarchy extends DataExtension {
/**
* Check if this DataObject is marked.
* @return boolean
*
* @return bool
*/
public function isMarked() {
$baseClass = ClassInfo::baseDataClass($this->owner->class);
@ -440,7 +465,8 @@ class Hierarchy extends DataExtension {
/**
* Check if this DataObject is expanded.
* @return boolean
*
* @return bool
*/
public function isExpanded() {
$baseClass = ClassInfo::baseDataClass($this->owner->class);
@ -450,6 +476,8 @@ class Hierarchy extends DataExtension {
/**
* Check if this DataObject's tree is opened.
*
* @return bool
*/
public function isTreeOpened() {
$baseClass = ClassInfo::baseDataClass($this->owner->class);
@ -459,7 +487,8 @@ class Hierarchy extends DataExtension {
/**
* Get a list of this DataObject's and all it's descendants IDs.
* @return int
*
* @return int[]
*/
public function getDescendantIDList() {
$idList = array();
@ -468,8 +497,9 @@ class Hierarchy extends DataExtension {
}
/**
* Get a list of this DataObject's and all it's descendants ID, and put it in $idList.
* @var array $idList Array to put results in.
* Get a list of this DataObject's and all it's descendants ID, and put them in $idList.
*
* @param array $idList Array to put results in.
*/
public function loadDescendantIDListInto(&$idList) {
if($children = $this->AllChildren()) {
@ -488,7 +518,8 @@ class Hierarchy extends DataExtension {
/**
* Get the children for this DataObject.
* @return ArrayList
*
* @return DataList
*/
public function Children() {
if(!(isset($this->_cache_children) && $this->_cache_children)) {
@ -506,7 +537,8 @@ class Hierarchy extends DataExtension {
/**
* Return all children, including those 'not in menus'.
* @return SS_List
*
* @return DataList
*/
public function AllChildren() {
return $this->owner->stageChildren(true);
@ -514,11 +546,13 @@ class Hierarchy extends DataExtension {
/**
* Return all children, including those that have been deleted but are still in live.
* Deleted children will be marked as "DeletedFromStage"
* Added children will be marked as "AddedToStage"
* Modified children will be marked as "ModifiedOnStage"
* Everything else has "SameOnStage" set, as an indicator that this information has been looked up.
* @return SS_List
* - Deleted children will be marked as "DeletedFromStage"
* - Added children will be marked as "AddedToStage"
* - Modified children will be marked as "ModifiedOnStage"
* - Everything else has "SameOnStage" set, as an indicator that this information has been looked up.
*
* @param mixed $context
* @return ArrayList
*/
public function AllChildrenIncludingDeleted($context = null) {
return $this->doAllChildrenIncludingDeleted($context);
@ -527,8 +561,8 @@ class Hierarchy extends DataExtension {
/**
* @see AllChildrenIncludingDeleted
*
* @param unknown_type $context
* @return SS_List
* @param mixed $context
* @return ArrayList
*/
public function doAllChildrenIncludingDeleted($context = null) {
if(!$this->owner) user_error('Hierarchy::doAllChildrenIncludingDeleted() called without $this->owner');
@ -560,8 +594,10 @@ class Hierarchy extends DataExtension {
}
/**
* Return all the children that this page had, including pages that were deleted
* from both stage & live.
* Return all the children that this page had, including pages that were deleted from both stage & live.
*
* @return DataList
* @throws Exception
*/
public function AllHistoricalChildren() {
if(!$this->owner->hasExtension('Versioned')) {
@ -574,7 +610,10 @@ class Hierarchy extends DataExtension {
}
/**
* Return the number of children that this page ever had, including pages that were deleted
* Return the number of children that this page ever had, including pages that were deleted.
*
* @return int
* @throws Exception
*/
public function numHistoricalChildren() {
if(!$this->owner->hasExtension('Versioned')) {
@ -586,11 +625,10 @@ class Hierarchy extends DataExtension {
}
/**
* Return the number of direct children.
* By default, values are cached after the first invocation.
* Can be augumented by {@link augmentNumChildrenCountQuery()}.
* Return the number of direct children. By default, values are cached after the first invocation. Can be
* augumented by {@link augmentNumChildrenCountQuery()}.
*
* @param Boolean $cache
* @param bool $cache Whether to retrieve values from cache
* @return int
*/
public function numChildren($cache = true) {
@ -606,10 +644,10 @@ class Hierarchy extends DataExtension {
}
/**
* Return children from the stage site
* Return children in the stage site.
*
* @param showAll Inlcude all of the elements, even those not shown in the menus.
* (only applicable when extension is applied to {@link SiteTree}).
* @param bool $showAll Include all of the elements, even those not shown in the menus. Only applicable when
* extension is applied to {@link SiteTree}.
* @return DataList
*/
public function stageChildren($showAll = false) {
@ -625,12 +663,13 @@ class Hierarchy extends DataExtension {
}
/**
* Return children from the live site, if it exists.
* Return children in the live site, if it exists.
*
* @param boolean $showAll Include all of the elements, even those not shown in the menus.
* (only applicable when extension is applied to {@link SiteTree}).
* @param boolean $onlyDeletedFromStage Only return items that have been deleted from stage
* @return SS_List
* @param bool $showAll Include all of the elements, even those not shown in the menus. Only
* applicable when extension is applied to {@link SiteTree}.
* @param bool $onlyDeletedFromStage Only return items that have been deleted from stage
* @return DataList
* @throws Exception
*/
public function liveChildren($showAll = false, $onlyDeletedFromStage = false) {
if(!$this->owner->hasExtension('Versioned')) {
@ -652,7 +691,10 @@ class Hierarchy extends DataExtension {
}
/**
* Get the parent of this class.
* Get this object's parent, optionally filtered by an SQL clause. If the clause doesn't match the parent, nothing
* is returned.
*
* @param string $filter
* @return DataObject
*/
public function getParent($filter = null) {
@ -669,7 +711,7 @@ class Hierarchy extends DataExtension {
/**
* Return all the parents of this class in a set ordered from the lowest to highest parent.
*
* @return SS_List
* @return ArrayList
*/
public function getAncestors() {
$ancestors = new ArrayList();
@ -683,11 +725,10 @@ class Hierarchy extends DataExtension {
}
/**
* Returns a human-readable, flattened representation of the path to the object,
* using its {@link Title()} attribute.
* Returns a human-readable, flattened representation of the path to the object, using its {@link Title} attribute.
*
* @param String
* @return String
* @param string $separator
* @return string
*/
public function getBreadcrumbs($separator = ' &raquo; ') {
$crumbs = array();
@ -702,22 +743,25 @@ class Hierarchy extends DataExtension {
* then search the parents.
*
* @todo Write!
*
* @param string $className Class name of the node to find
* @param DataObject $afterNode Used for recursive calls to this function
* @return DataObject
*/
public function naturalPrev( $className, $afterNode = null ) {
public function naturalPrev($className, $afterNode = null ) {
return null;
}
/**
* Get the next node in the tree of the type. If there is no instance of the className descended from this node,
* then search the parents.
* @param string $className Class name of the node to find.
* @param string|int $root ID/ClassName of the node to limit the search to
* @param DataObject afterNode Used for recursive calls to this function
* @param string $className Class name of the node to find.
* @param string|int $root ID/ClassName of the node to limit the search to
* @param DataObject $afterNode Used for recursive calls to this function
* @return DataObject
*/
public function naturalNext( $className = null, $root = 0, $afterNode = null ) {
// If this node is not the node we are searching from, then we can possibly return this
// node as a solution
public function naturalNext($className = null, $root = 0, $afterNode = null ) {
// If this node is not the node we are searching from, then we can possibly return this node as a solution
if($afterNode && $afterNode->ID != $this->owner->ID) {
if(!$className || ($className && $this->owner->class == $className)) {
return $this->owner;
@ -761,6 +805,14 @@ class Hierarchy extends DataExtension {
return null;
}
/**
* Flush all Hierarchy caches:
* - Children (instance)
* - NumChildren (instance)
* - Marked (global)
* - Expanded (global)
* - TreeOpened (global)
*/
public function flushCache() {
$this->_cache_children = null;
$this->_cache_numChildren = null;
@ -769,6 +821,12 @@ class Hierarchy extends DataExtension {
self::$treeOpened = array();
}
/**
* Reset global Hierarchy caches:
* - Marked
* - Expanded
* - TreeOpened
*/
public static function reset() {
self::$marked = array();
self::$expanded = array();

View File

@ -1,16 +1,24 @@
<?php
/**
* 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.
* 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.
*
* @property int $Version
*
* @package framework
* @subpackage model
*
* @property DataObject owner
*
* @property int RecordID
* @property int Version
* @property bool WasPublished
* @property int AuthorID
* @property int PublisherID
*/
class Versioned extends DataExtension implements TemplateGlobalProvider {
/**
* An array of possible stages.
* @var array
@ -35,40 +43,33 @@ class Versioned extends DataExtension implements TemplateGlobalProvider {
const DEFAULT_MODE = 'Stage.Live';
/**
* A version that a DataObject should be when it is 'migrating',
* that is, when it is in the process of moving from one stage to another.
* A version that a DataObject should be when it is 'migrating', that is, when it is in the process of moving from
* one stage to another.
* @var string
*/
public $migratingVersion;
/**
* A cache used by get_versionnumber_by_stage().
* Clear through {@link flushCache()}.
*
* A cache used by get_versionnumber_by_stage(). Clear through {@link flushCache()}.
* @var array
*/
protected static $cache_versionnumber;
/**
* @var string
*/
/** @var string */
protected static $reading_mode = null;
/**
* @var Boolean Flag which is temporarily changed during the write() process
* to influence augmentWrite() behaviour. If set to TRUE, no new version will be created
* for the following write. Needs to be public as other classes introspect this state
* during the write process in order to adapt to this versioning behaviour.
* Flag which is temporarily changed during the write() process to influence augmentWrite() behaviour. If set to
* true, no new version will be created for the following write. Needs to be public as other classes introspect this
* state during the write process in order to adapt to this versioning behaviour.
* @var bool
*/
public $_nextWriteWithoutVersion = false;
/**
* Additional database columns for the new
* "_versions" table. Used in {@link augmentDatabase()}
* and all Versioned calls extending or creating
* SELECT statements.
*
* @var array $db_for_versions_table
* Additional database columns for the new "_versions" table. Used in {@link augmentDatabase()} and all Versioned
* calls extending or creating SELECT statements.
* @var array
*/
private static $db_for_versions_table = array(
"RecordID" => "Int",
@ -78,33 +79,25 @@ class Versioned extends DataExtension implements TemplateGlobalProvider {
"PublisherID" => "Int"
);
/**
* @var array
*/
private static $db = array(
'Version' => 'Int'
);
/**
* Used to enable or disable the prepopulation of the version number cache.
* Defaults to true.
*
* @var boolean
*/
* Used to enable or disable the prepopulation of the version number cache. Defaults to true.
* @var bool
*/
private static $prepopulate_versionnumber_cache = true;
/**
* Keep track of the archive tables that have been created.
*
* @var array
*/
private static $archive_tables = array();
/**
* Additional database indexes for the new
* "_versions" table. Used in {@link augmentDatabase()}.
*
* @var array $indexes_for_versions_table
* Additional database indexes for the new "_versions" table. Used in {@link augmentDatabase()}.
* @var array
*/
private static $indexes_for_versions_table = array(
'RecordID_Version' => '("RecordID","Version")',
@ -116,10 +109,9 @@ class Versioned extends DataExtension implements TemplateGlobalProvider {
/**
* 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 '_'.
* E.g. if Extension1 creates a new table 'Class_suffix1'
* and Extension2 the tables 'Class_suffix2' and 'Class_suffix3':
* 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 '_'. E.g. if Extension1 creates a new table
* 'Class_suffix1' and Extension2 the tables 'Class_suffix2' and 'Class_suffix3':
*
* $versionableExtensions = array(
* 'Extension1' => 'suffix1',
@ -142,9 +134,7 @@ class Versioned extends DataExtension implements TemplateGlobalProvider {
* Config::inst()->update($this->owner->class, 'versionableExtensions',
* array('Extension1' => 'suffix1', 'Extension2' => array('suffix2', 'suffix3')));
*
*
* Make sure your extension has a static $enabled-property that determines if it is
* processed by Versioned.
* Make sure your extension has a static $enabled-property that determines if it is processed by Versioned.
*
* @var array
*/
@ -170,9 +160,8 @@ class Versioned extends DataExtension implements TemplateGlobalProvider {
/**
* Construct a new Versioned object.
*
* @var array $stages The different stages the versioned object can be.
* The first stage is considered the 'default' stage, the last stage is
* considered the 'live' stage.
* @param array $stages The different stages the versioned object can be. The first stage is considered the
* 'default' stage, the last stage is considered the 'live' stage.
*/
public function __construct($stages = array('Stage','Live')) {
parent::__construct();
@ -187,11 +176,10 @@ class Versioned extends DataExtension implements TemplateGlobalProvider {
}
/**
* Amend freshly created DataQuery objects with versioned-specific
* information.
* Amend freshly created DataQuery objects with versioned-specific information.
*
* @param SQLQuery
* @param DataQuery
* @param SQLQuery $query
* @param DataQuery $dataQuery
*/
public function augmentDataQueryCreation(SQLQuery &$query, DataQuery &$dataQuery) {
$parts = explode('.', Versioned::get_reading_mode());
@ -206,12 +194,14 @@ class Versioned extends DataExtension implements TemplateGlobalProvider {
$dataQuery->setQueryParam('Versioned.mode', 'stage');
$dataQuery->setQueryParam('Versioned.stage', $parts[1]);
}
}
/**
* Augment the the SQLQuery that is created by the DataQuery
* Augment the the SQLQuery that is created by the DataQuery.
* @todo Should this all go into VersionedDataQuery?
*
* @param SQLQuery $query
* @param DataQuery $dataQuery
*/
public function augmentSQL(SQLQuery &$query, DataQuery &$dataQuery = null) {
if(!$dataQuery || !$dataQuery->getQueryParam('Versioned.mode')) {
@ -328,9 +318,8 @@ class Versioned extends DataExtension implements TemplateGlobalProvider {
}
$query->setOrderBy($orders);
// latest_version has one more step
// Return latest version instances, regardless of whether they are on a particular stage
// This provides "show all, including deleted" functonality
// latest_version has one more step. Return latest version instances, regardless of whether they are on a
// particular stage. This provides "show all, including deleted" functonality
if($dataQuery->getQueryParam('Versioned.mode') == 'latest_versions') {
$query->addWhere(
"\"{$alias}_versions\".\"Version\" IN
@ -355,17 +344,16 @@ class Versioned extends DataExtension implements TemplateGlobalProvider {
}
/**
* For lazy loaded fields requiring extra sql manipulation, ie versioning.
* For lazy loaded fields requiring extra SQL manipulation, ie versioning.
*
* @param SQLQuery $query
* @param DataQuery $dataQuery
* @param SQLQuery $query
* @param DataQuery $dataQuery
* @param DataObject $dataObject
*/
public function augmentLoadLazyFields(SQLQuery &$query, DataQuery &$dataQuery = null, $dataObject) {
// The VersionedMode local variable ensures that this decorator only applies to
// queries that have originated from the Versioned object, and have the Versioned
// metadata set on the query object. This prevents regular queries from
// accidentally querying the *_versions tables.
// The VersionedMode local variable ensures that this decorator only applies to queries that have originated
// from the Versioned object, and have the Versioned metadata set on the query object. This prevents regular
// queries from accidentally querying the *_versions tables.
$versionedMode = $dataObject->getSourceQueryParam('Versioned.mode');
$dataClass = $dataQuery->dataClass();
$modesToAllowVersioning = array('all_versions', 'latest_versions', 'archive');
@ -382,7 +370,6 @@ class Versioned extends DataExtension implements TemplateGlobalProvider {
}
}
/**
* Called by {@link SapphireTest} when the database is reset.
*
@ -498,8 +485,8 @@ class Versioned extends DataExtension implements TemplateGlobalProvider {
}
if(DB::get_schema()->hasTable("{$table}_versions")) {
// Fix data that lacks the uniqueness constraint (since this was added later and
// bugs meant that the constraint was validated)
// Fix data that lacks the uniqueness constraint (since this was added later and bugs meant that
// the constraint was validated)
$duplications = DB::query("SELECT MIN(\"ID\") AS \"ID\", \"RecordID\", \"Version\"
FROM \"{$table}_versions\" GROUP BY \"RecordID\", \"Version\"
HAVING COUNT(*) > 1");
@ -514,8 +501,8 @@ class Versioned extends DataExtension implements TemplateGlobalProvider {
);
}
// Remove junk which has no data in parent classes. Only needs to run the following
// when versioned data is spread over multiple tables
// Remove junk which has no data in parent classes. Only needs to run the following when versioned
// data is spread over multiple tables
if(!$isRootClass && ($versionedTables = ClassInfo::dataClassesFor($table))) {
foreach($versionedTables as $child) {
@ -595,9 +582,7 @@ class Versioned extends DataExtension implements TemplateGlobalProvider {
/**
* Generates a ($table)_version DB manipulation and injects it into the current $manipulation
*
* @param array $manipulation Source manipulation data
* @param string $table Name of table
* @param int $recordID ID of record to version
* @param SQLQuery $manipulation The query to augment
*/
protected function augmentWriteVersioned(&$manipulation, $table, $recordID) {
$baseDataClass = ClassInfo::baseDataClass($table);
@ -740,8 +725,7 @@ class Versioned extends DataExtension implements TemplateGlobalProvider {
$this->migrateVersion(null);
}
// Add the new version # back into the data object, for accessing
// after this write
// Add the new version # back into the data object, for accessing after this write
if(isset($thisVersion)) {
$this->owner->Version = str_replace("'","", $thisVersion);
}
@ -749,9 +733,8 @@ class Versioned extends DataExtension implements TemplateGlobalProvider {
/**
* Perform a write without affecting the version table.
* On objects without versioning.
*
* @return int The ID of the record
* @return int The ID of the written record
*/
public function writeWithoutVersion() {
$this->_nextWriteWithoutVersion = true;
@ -759,18 +742,13 @@ class Versioned extends DataExtension implements TemplateGlobalProvider {
return $this->owner->write();
}
/**
*
*/
public function onAfterWrite() {
$this->_nextWriteWithoutVersion = false;
}
/**
* If a write was skipped, then we need to ensure that we don't leave a
* migrateVersion() value lying around for the next write.
*
*
* If a write was skipped, then we need to ensure that we don't leave a migrateVersion() value lying around for the
* next write.
*/
public function onAfterSkippedWrite() {
$this->migrateVersion(null);
@ -867,11 +845,10 @@ class Versioned extends DataExtension implements TemplateGlobalProvider {
}
/**
* Determine if a table is supporting the Versioned extensions (e.g.
* $table_versions does exists).
* Determine if a table supports the Versioned extensions (e.g. $table_versions does exists).
*
* @param string $table Table name
* @return boolean
* @return bool
*/
public function canBeVersioned($table) {
return ClassInfo::exists($table)
@ -883,8 +860,7 @@ class Versioned extends DataExtension implements TemplateGlobalProvider {
* Check if a certain table has the 'Version' field.
*
* @param string $table Table name
*
* @return boolean Returns false if the field isn't in the table, true otherwise
* @return bool
*/
public function hasVersionField($table) {
$rPos = strrpos($table,'_');
@ -900,7 +876,6 @@ class Versioned extends DataExtension implements TemplateGlobalProvider {
/**
* @param string $table
*
* @return string
*/
public function extendWithSuffix($table) {
@ -921,7 +896,7 @@ class Versioned extends DataExtension implements TemplateGlobalProvider {
}
/**
* Get the latest published DataObject.
* Get the latest published version of this object.
*
* @return DataObject
*/
@ -942,10 +917,10 @@ class Versioned extends DataExtension implements TemplateGlobalProvider {
/**
* Move a database record from one stage to the other.
*
* @param int|string $fromStage Place to copy from. Can be either a stage name or a version number.
* @param string $toStage Place to copy to. Must be a stage name.
* @param bool $createNewVersion Set this to true to create a new version number.
* By default, the existing version number will be copied over.
* @param string $fromStage Place to copy from. Can be either a stage name or a version number.
* @param string $toStage Place to copy to. Must be a stage name.
* @param bool $createNewVersion Set this to true to create a new version number. By default, the existing
* version number will be copied over.
*/
public function publish($fromStage, $toStage, $createNewVersion = false) {
$this->owner->extend('onBeforeVersionedPublish', $fromStage, $toStage, $createNewVersion);
@ -1005,19 +980,18 @@ class Versioned extends DataExtension implements TemplateGlobalProvider {
/**
* Set the migrating version.
*
* @param string $version The version.
* @param string $version
*/
public function migrateVersion($version) {
$this->migratingVersion = $version;
}
/**
* Compare two stages to see if they're different.
* Compare two stages to see if they're different. Only checks the version numbers, not the actual content.
*
* Only checks the version numbers, not the actual content.
*
* @param string $stage1 The first stage to check.
* @param string $stage2
* @param string $stage1 The first stage to check
* @param string $stage2 The second stage to check
* @return bool
*/
public function stagesDiffer($stage1, $stage2) {
$table1 = $this->baseTable($stage1);
@ -1027,8 +1001,7 @@ class Versioned extends DataExtension implements TemplateGlobalProvider {
return true;
}
// We test for equality - if one of the versions doesn't exist, this
// will be false.
// We test for equality - if one of the versions doesn't exist, this will be false.
// TODO: DB Abstraction: if statement here:
$stagesAreEqual = DB::prepared_query(
@ -1042,24 +1015,28 @@ class Versioned extends DataExtension implements TemplateGlobalProvider {
}
/**
* Get a list of versions for this object, optionally with additional SQL parameters
*
* @param string $filter
* @param string $sort
* @param string $limit
* @param string $join Deprecated, use leftJoin($table, $joinClause) instead
* @param string $having
* @return DataList
*/
public function Versions($filter = "", $sort = "", $limit = "", $join = "", $having = "") {
return $this->allVersions($filter, $sort, $limit, $join, $having);
}
/**
* Return a list of all the versions available.
* Get a list of versions for this object, optionally with additional SQL parameters
*
* @param string $filter
* @param string $sort
* @param string $limit
* @param string $join Deprecated, use leftJoin($table, $joinClause) instead
* @param string $join Deprecated, use leftJoin($table, $joinClause) instead
* @param string $having
* @return DataList
*/
public function allVersions($filter = "", $sort = "", $limit = "", $join = "", $having = "") {
// Make sure the table names are not postfixed (e.g. _Live)
@ -1106,11 +1083,10 @@ class Versioned extends DataExtension implements TemplateGlobalProvider {
}
/**
* Compare two version, and return the diff between them.
*
* @param string $from The version to compare from.
* @param string $to The version to compare to.
* Compare two version, and return the differences between them.
*
* @param string $from The version to compare from
* @param string $to The version to compare to
* @return DataObject
*/
public function compareVersions($from, $to) {
@ -1125,6 +1101,7 @@ class Versioned extends DataExtension implements TemplateGlobalProvider {
/**
* Return the base table - the class that directly extends DataObject.
*
* @param string $stage Override the stage used
* @return string
*/
public function baseTable($stage = null) {
@ -1162,16 +1139,12 @@ class Versioned extends DataExtension implements TemplateGlobalProvider {
}
/**
* Choose the stage the site is currently on.
* 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'.
*
* 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'.
* @param Session $session Optional session within which to store the resulting stage
*/
public static function choose_site_stage() {
// Check any pre-existing session mode
@ -1268,7 +1241,7 @@ class Versioned extends DataExtension implements TemplateGlobalProvider {
/**
* Set the reading stage.
*
* @param string $stage New reading stage.
* @param string $stage
*/
public static function reading_stage($stage) {
Versioned::set_reading_mode('Stage.' . $stage);
@ -1277,21 +1250,20 @@ class Versioned extends DataExtension implements TemplateGlobalProvider {
/**
* Set the reading archive date.
*
* @param string $date New reading archived date.
* @param string $date
*/
public static function reading_archived_date($date) {
Versioned::set_reading_mode('Archive.' . $date);
}
/**
* Get a singleton instance of a class in the given stage.
*
* @param string $class The name of the class.
* @param string $stage The name of the stage.
* @param string $filter A filter to be inserted into the WHERE clause.
* @param boolean $cache Use caching.
* @param string $orderby A sort expression to be inserted into the ORDER BY clause.
* @param string $class The name of the class
* @param string $stage The name of the stage
* @param string $filter A filter to be inserted into the WHERE clause
* @param bool $cache Whether to load from the cache instead of fresh from the database
* @param string $sort A sort expression to be inserted into the ORDER BY clause.
*
* @return DataObject
*/
@ -1305,10 +1277,10 @@ class Versioned extends DataExtension implements TemplateGlobalProvider {
/**
* Gets the current version number of a specific record.
*
* @param string $class
* @param string $stage
* @param int $id
* @param boolean $cache
* @param string $class The classname of the desired object
* @param string $stage The name of the stage to load from
* @param int $id The object's ID
* @param bool $cache Whether to load from the cache instead of fresh from the database
*
* @return int
*/
@ -1321,11 +1293,8 @@ class Versioned extends DataExtension implements TemplateGlobalProvider {
return self::$cache_versionnumber[$baseClass][$stage][$id];
}
// get version as performance-optimized SQL query (gets called for each page in the sitetree)
$version = DB::prepared_query(
"SELECT \"Version\" FROM \"$stageTable\" WHERE \"ID\" = ?",
array($id)
)->value();
// get version as performance-optimized SQL query (gets called for each object of this class in the database)
$version = DB::query("SELECT \"Version\" FROM \"$stageTable\" WHERE \"ID\" = $id")->value();
// cache value (if required)
if($cache) {
@ -1344,13 +1313,12 @@ class Versioned extends DataExtension implements TemplateGlobalProvider {
}
/**
* 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 page will be pre-cached.
* Prepopulate 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 object will be pre-cached.
*
* @param string $class
* @param string $stage
* @param array $idList
* @param string $class The object class to prepopulate version numbers for
* @param string $stage The stage to prepopulate version numbers from
* @param array $idList A whitelist of IDs to use when prepopulating
*/
public static function prepopulate_versionnumber_cache($class, $stage, $idList = null) {
if (!Config::inst()->get('Versioned', 'prepopulate_versionnumber_cache')) {
@ -1383,13 +1351,13 @@ class Versioned extends DataExtension implements TemplateGlobalProvider {
/**
* Get a set of class instances by the given stage.
*
* @param string $class The name of the class.
* @param string $stage The name of the stage.
* @param string $filter A filter to be inserted into the WHERE clause.
* @param string $sort A sort expression to be inserted into the ORDER BY clause.
* @param string $join Deprecated, use leftJoin($table, $joinClause) instead
* @param int $limit A limit on the number of records returned from the database.
* @param string $containerClass The container class for the result set (default is DataList)
* @param string $class The name of the class.
* @param string $stage The name of the stage.
* @param string $filter A filter to be inserted into the WHERE clause.
* @param string $sort A sort expression to be inserted into the ORDER BY clause.
* @param string $join Deprecated, use leftJoin($table, $joinClause) instead
* @param string|int $limit A limit on the number of records returned from the database.
* @param string $containerClass The container class for the result set (default is DataList)
*
* @return DataList A modified DataList designated to the specified stage
*/
@ -1404,9 +1372,9 @@ class Versioned extends DataExtension implements TemplateGlobalProvider {
}
/**
* @param string $stage
* Delete this item from the specified stage.
*
* @return int
* @param string $stage
*/
public function deleteFromStage($stage) {
$oldMode = Versioned::get_reading_mode();
@ -1423,8 +1391,11 @@ class Versioned extends DataExtension implements TemplateGlobalProvider {
}
/**
* @param string $stage
* @param boolean $forceInsert
* Write this item to the specified stage.
*
* @param string $stage The stage to write this item to
* @param bool $forceInsert Whether to force an INSERT query over an UPDATE query
* @return int The ID of the item being written
*/
public function writeToStage($stage, $forceInsert = false) {
$oldMode = Versioned::get_reading_mode();
@ -1438,10 +1409,11 @@ class Versioned extends DataExtension implements TemplateGlobalProvider {
}
/**
* Roll the draft version of this page to match the published page.
* Roll the draft version of this object to match the published one.
*
* Caution: Doesn't overwrite the object properties with the rolled back version.
*
* @param int $version Either the string 'Live' or a version number
* @param string|int $version Either the string 'Live' or a version number
*/
public function doRollbackTo($version) {
$this->owner->extend('onBeforeRollback', $version);
@ -1453,8 +1425,10 @@ class Versioned extends DataExtension implements TemplateGlobalProvider {
}
/**
* Return the latest version of the given page.
* Return the latest version of the given object.
*
* @param string $class The classname of the object to lookup
* @param string $id The object of the ID to retrieve
* @return DataObject
*/
public static function get_latest_version($class, $id) {
@ -1474,7 +1448,7 @@ class Versioned extends DataExtension implements TemplateGlobalProvider {
* @see get_latest_version()
* @see latestPublished
*
* @return boolean
* @return bool
*/
public function isLatestVersion() {
$version = self::get_latest_version($this->owner->class, $this->owner->ID);
@ -1486,14 +1460,12 @@ class Versioned extends DataExtension implements TemplateGlobalProvider {
}
/**
* Return the equivalent of a DataList::create() call, querying the latest
* version of each page stored in the (class)_versions tables.
* Return the equivalent of a DataList::create() call, querying the latest version of each object stored in the
* (class)_versions tables. In particular, this will query deleted records as well as active ones.
*
* In particular, this will query deleted records as well as active ones.
*
* @param string $class
* @param string $filter
* @param string $sort
* @param string $class The type of object to lookup
* @param string $filter An optional SQL comparison to add to the WHERE clause
* @param string $sort An optional SQL statement to add to the SORT clause
*/
public static function get_including_deleted($class, $filter = "", $sort = "") {
$list = DataList::create($class)
@ -1505,16 +1477,14 @@ class Versioned extends DataExtension implements TemplateGlobalProvider {
}
/**
* 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.
*
* @param string $class
* @param int $id
* @param int $version
* 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.
*
* @param string $class The type of object to lookup
* @param int $id The ID of the object to retrieve
* @param int $version The desired version of the object
* @return DataObject
*/
public static function get_version($class, $id, $version) {
@ -1530,8 +1500,8 @@ class Versioned extends DataExtension implements TemplateGlobalProvider {
/**
* Return a list of all versions for a given id.
*
* @param string $class
* @param int $id
* @param string $class The type of object to lookup
* @param int $id The ID of the object to retrieve
*
* @return DataList
*/
@ -1551,9 +1521,6 @@ class Versioned extends DataExtension implements TemplateGlobalProvider {
$labels['Versions'] = _t('Versioned.has_many_Versions', 'Versions', 'Past Versions of this page');
}
/**
* @param FieldList
*/
public function updateCMSFields(FieldList $fields) {
// remove the version field from the CMS as this should be left
// entirely up to the extension (not the cms user).
@ -1570,12 +1537,15 @@ class Versioned extends DataExtension implements TemplateGlobalProvider {
$this->owner->Version = 0;
}
/**
* Clear the cached version numbers from previous queries.
*/
public function flushCache() {
self::$cache_versionnumber = array();
}
/**
* Return a piece of text to keep DataObject cache keys appropriately specific.
* Returns a piece of text to keep DataObject cache keys appropriately specific.
*
* @return string
*/
@ -1615,14 +1585,11 @@ class Versioned extends DataExtension implements TemplateGlobalProvider {
* @see Versioned
*/
class Versioned_Version extends ViewableData {
/**
* @var array
*/
/** @var array */
protected $record;
/**
* @var DataObject
*/
/** @var DataObject */
protected $object;
public function __construct($record) {
@ -1637,6 +1604,8 @@ class Versioned_Version extends ViewableData {
}
/**
* Get a CSS classname to use representing whether this version was published or not.
*
* @return string
*/
public function PublishedClass() {
@ -1644,6 +1613,8 @@ class Versioned_Version extends ViewableData {
}
/**
* Gets this version's author (the person who saved to Stage).
*
* @return Member
*/
public function Author() {
@ -1651,6 +1622,8 @@ class Versioned_Version extends ViewableData {
}
/**
* Get this version's publisher.
*
* @return Member
*/
public function Publisher() {
@ -1662,7 +1635,9 @@ class Versioned_Version extends ViewableData {
}
/**
* @return boolean
* Determines if this version was ever published.
*
* @return bool
*/
public function Published() {
return !empty($this->record['WasPublished']);
@ -1670,6 +1645,9 @@ class Versioned_Version extends ViewableData {
/**
* Copied from DataObject to allow access via dot notation.
*
* @param string $fieldName
* @return mixed
*/
public function relField($fieldName) {
$component = $this;