mirror of
https://github.com/silverstripe/silverstripe-framework
synced 2024-10-22 14:05:37 +02:00
ENHANCEMENT: Improved Versioned to pass different query styles as DataQuery modes.
This commit is contained in:
parent
319d2f4952
commit
c57378753d
@ -111,13 +111,14 @@ class Versioned extends DataExtension {
|
|||||||
* Amend freshly created DataQuery objects with versioned-specific information
|
* Amend freshly created DataQuery objects with versioned-specific information
|
||||||
*/
|
*/
|
||||||
function augmentDataQueryCreation(SQLQuery &$query, DataQuery &$dataQuery) {
|
function augmentDataQueryCreation(SQLQuery &$query, DataQuery &$dataQuery) {
|
||||||
if($date = Versioned::$reading_archived_date) {
|
$parts = explode('.', Versioned::get_reading_mode());
|
||||||
|
if($parts[0] == 'Archive') {
|
||||||
$dataQuery->setQueryParam('Versioned.mode', 'archive');
|
$dataQuery->setQueryParam('Versioned.mode', 'archive');
|
||||||
$dataQuery->setQueryParam('Versioned.date', Versioned::$reading_archived_date);
|
$dataQuery->setQueryParam('Versioned.date', $parts[1]);
|
||||||
|
|
||||||
} else if(Versioned::$reading_stage && Versioned::$reading_stage != $this->defaultStage && array_search(Versioned::$reading_stage,$this->stages) !== false) {
|
} else if($parts[0] == 'Stage' && $parts[1] != $this->defaultStage && array_search($parts[1],$this->stages) !== false) {
|
||||||
$dataQuery->setQueryParam('Versioned.mode', 'stage');
|
$dataQuery->setQueryParam('Versioned.mode', 'stage');
|
||||||
$dataQuery->setQueryParam('Versioned.stage', Versioned::$reading_stage);
|
$dataQuery->setQueryParam('Versioned.stage', $parts[1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -127,14 +128,17 @@ class Versioned extends DataExtension {
|
|||||||
* @todo Should this all go into VersionedDataQuery?
|
* @todo Should this all go into VersionedDataQuery?
|
||||||
*/
|
*/
|
||||||
function augmentSQL(SQLQuery &$query, DataQuery &$dataQuery) {
|
function augmentSQL(SQLQuery &$query, DataQuery &$dataQuery) {
|
||||||
|
$baseTable = ClassInfo::baseDataClass($dataQuery->dataClass());
|
||||||
|
|
||||||
switch($dataQuery->getQueryParam('Versioned.mode')) {
|
switch($dataQuery->getQueryParam('Versioned.mode')) {
|
||||||
|
// Noop
|
||||||
|
case '':
|
||||||
|
break;
|
||||||
|
|
||||||
// Reading a specific data from the archive
|
// Reading a specific data from the archive
|
||||||
case 'archive':
|
case 'archive':
|
||||||
$date = $dataQuery->getQueryParam('Versioned.date');
|
$date = $dataQuery->getQueryParam('Versioned.date');
|
||||||
foreach($query->from as $table => $dummy) {
|
foreach($query->from as $table => $dummy) {
|
||||||
if(!isset($baseTable)) {
|
|
||||||
$baseTable = $table;
|
|
||||||
}
|
|
||||||
$query->renameTable($table, $table . '_versions');
|
$query->renameTable($table, $table . '_versions');
|
||||||
$query->replaceText("\"$table\".\"ID\"", "\"$table\".\"RecordID\"");
|
$query->replaceText("\"$table\".\"ID\"", "\"$table\".\"RecordID\"");
|
||||||
|
|
||||||
@ -172,6 +176,36 @@ class Versioned extends DataExtension {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
||||||
|
// Return all version instances
|
||||||
|
case 'all_versions':
|
||||||
|
case 'latest_versions':
|
||||||
|
foreach($query->from as $alias => $join) {
|
||||||
|
if($alias != $baseTable) {
|
||||||
|
$query->setJoinFilter($alias, "\"$alias\".\"RecordID\" = \"{$baseTable}_versions\".\"RecordID\" AND \"$alias\".\"Version\" = \"{$baseTable}_versions\".\"Version\"");
|
||||||
|
}
|
||||||
|
$query->renameTable($alias, $alias . '_versions');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add all <basetable>_versions columns
|
||||||
|
foreach(self::$db_for_versions_table as $name => $type) {
|
||||||
|
$query->selectMore(sprintf('"%s_versions"."%s"', $baseTable, $name));
|
||||||
|
}
|
||||||
|
$query->selectMore(sprintf('"%s_versions"."%s" AS "ID"', $baseTable, 'RecordID'));
|
||||||
|
|
||||||
|
// 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') {
|
||||||
|
$archiveTable = self::requireArchiveTempTable($baseTable);
|
||||||
|
$query->innerJoin($archiveTable, "\"$archiveTable\".\"ID\" = \"{$baseTable}_versions\".\"RecordID\" AND \"$archiveTable\".\"Version\" = \"{$baseTable}_versions\".\"Version\"");
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
throw new InvalidArgumentException("Bad value for query parameter Versioned.mode: " . $dataQuery->getQueryParam('Versioned.mode'));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -803,16 +837,10 @@ class Versioned extends DataExtension {
|
|||||||
* @param string $orderby A sort expression to be inserted into the ORDER BY clause.
|
* @param string $orderby A sort expression to be inserted into the ORDER BY clause.
|
||||||
* @return DataObject
|
* @return DataObject
|
||||||
*/
|
*/
|
||||||
static function get_one_by_stage($class, $stage, $filter = '', $cache = true, $orderby = '') {
|
static function get_one_by_stage($class, $stage, $filter = '', $cache = true, $sort = '') {
|
||||||
$oldMode = Versioned::get_reading_mode();
|
// TODO: No identity cache operating
|
||||||
Versioned::reading_stage($stage);
|
$items = self::get_by_stage($class, $stage, $filter, $sort, null, 1);
|
||||||
|
return $items->First();
|
||||||
singleton($class)->flushCache();
|
|
||||||
$result = DataObject::get_one($class, $filter, $cache, $orderby);
|
|
||||||
singleton($class)->flushCache();
|
|
||||||
|
|
||||||
Versioned::set_reading_mode($oldMode);
|
|
||||||
return $result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -920,69 +948,16 @@ class Versioned extends DataExtension {
|
|||||||
$this->owner->writeWithoutVersion();
|
$this->owner->writeWithoutVersion();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Build a SQL query to get data from the _version table.
|
|
||||||
* This function is similar in style to {@link DataObject::buildSQL}
|
|
||||||
*/
|
|
||||||
function buildVersionSQL($filter = "", $sort = "") {
|
|
||||||
$query = $this->owner->extendedSQL($filter,$sort);
|
|
||||||
foreach($query->from as $table => $join) {
|
|
||||||
if($join[0] == '"') $baseTable = str_replace('"','',$join);
|
|
||||||
else $query->from[$table] = "LEFT JOIN \"$table\" ON \"$table\".\"RecordID\" = \"{$baseTable}_versions\".\"RecordID\" AND \"$table\".\"Version\" = \"{$baseTable}_versions\".\"Version\"";
|
|
||||||
$query->renameTable($table, $table . '_versions');
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add all <basetable>_versions columns
|
|
||||||
foreach(self::$db_for_versions_table as $name => $type) {
|
|
||||||
$query->select[] = sprintf('"%s_versions"."%s"', $baseTable, $name);
|
|
||||||
}
|
|
||||||
$query->select[] = sprintf('"%s_versions"."%s" AS "ID"', $baseTable, 'RecordID');
|
|
||||||
|
|
||||||
return $query;
|
|
||||||
}
|
|
||||||
|
|
||||||
static function build_version_sql($className, $filter = "", $sort = "") {
|
|
||||||
$query = singleton($className)->extendedSQL($filter,$sort);
|
|
||||||
foreach($query->from as $table => $join) {
|
|
||||||
if($join[0] == '"') $baseTable = str_replace('"','',$join);
|
|
||||||
else $query->from[$table] = "LEFT JOIN \"$table\" ON \"$table\".\"RecordID\" = \"{$baseTable}_versions\".\"RecordID\" AND \"$table\".\"Version\" = \"{$baseTable}_versions\".\"Version\"";
|
|
||||||
$query->renameTable($table, $table . '_versions');
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add all <basetable>_versions columns
|
|
||||||
foreach(self::$db_for_versions_table as $name => $type) {
|
|
||||||
$query->select[] = sprintf('"%s_versions"."%s"', $baseTable, $name);
|
|
||||||
}
|
|
||||||
$query->select[] = sprintf('"%s_versions"."%s" AS "ID"', $baseTable, 'RecordID');
|
|
||||||
|
|
||||||
return $query;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the latest version of the given page.
|
* Return the latest version of the given page.
|
||||||
*
|
*
|
||||||
* @return DataObject
|
* @return DataObject
|
||||||
*/
|
*/
|
||||||
static function get_latest_version($class, $id) {
|
static function get_latest_version($class, $id) {
|
||||||
$oldMode = Versioned::get_reading_mode();
|
$baseClass = ClassInfo::baseDataClass($class);
|
||||||
Versioned::set_reading_mode('');
|
$list = DataList::create($class)->filter("\"$baseClass\".\"RecordID\" = $id");
|
||||||
|
$list->dataQuery()->setQueryParam("Versioned.mode", "latest_versions");
|
||||||
$baseTable = ClassInfo::baseDataClass($class);
|
return $list->First();
|
||||||
$query = singleton($class)->buildVersionSQL("\"{$baseTable}\".\"RecordID\" = $id", "\"{$baseTable}\".\"Version\" DESC");
|
|
||||||
$query->limit = 1;
|
|
||||||
$record = $query->execute()->record();
|
|
||||||
if(!$record) return;
|
|
||||||
|
|
||||||
$className = $record['ClassName'];
|
|
||||||
if(!$className) {
|
|
||||||
Debug::show($query->sql());
|
|
||||||
Debug::show($record);
|
|
||||||
user_error("Versioned::get_version: Couldn't get $class.$id", E_USER_ERROR);
|
|
||||||
}
|
|
||||||
|
|
||||||
Versioned::set_reading_mode($oldMode);
|
|
||||||
|
|
||||||
return new $className($record);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -992,61 +967,31 @@ class Versioned extends DataExtension {
|
|||||||
* In particular, this will query deleted records as well as active ones.
|
* In particular, this will query deleted records as well as active ones.
|
||||||
*/
|
*/
|
||||||
static function get_including_deleted($class, $filter = "", $sort = "") {
|
static function get_including_deleted($class, $filter = "", $sort = "") {
|
||||||
$oldMode = Versioned::get_reading_mode();
|
$list = DataList::create($class)->filter($filter)->sort($sort);
|
||||||
Versioned::set_reading_mode('');
|
$list->dataQuery()->setQueryParam("Versioned.mode", "latest_versions");
|
||||||
|
return $list;
|
||||||
$SNG = singleton($class);
|
|
||||||
|
|
||||||
// Build query
|
|
||||||
$query = $SNG->buildVersionSQL($filter, $sort);
|
|
||||||
$baseTable = ClassInfo::baseDataClass($class);
|
|
||||||
$archiveTable = self::requireArchiveTempTable($baseTable);
|
|
||||||
$query->from[$archiveTable] = "INNER JOIN \"$archiveTable\"
|
|
||||||
ON \"$archiveTable\".\"ID\" = \"{$baseTable}_versions\".\"RecordID\"
|
|
||||||
AND \"$archiveTable\".\"Version\" = \"{$baseTable}_versions\".\"Version\"";
|
|
||||||
|
|
||||||
// Process into a DataObjectSet
|
|
||||||
$result = $SNG->buildDataObjectSet($query->execute(), 'DataObjectSet', null, $class);
|
|
||||||
|
|
||||||
Versioned::set_reading_mode($oldMode);
|
|
||||||
return $query;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Return the specific version of the given id
|
||||||
* @return DataObject
|
* @return DataObject
|
||||||
*/
|
*/
|
||||||
static function get_version($class, $id, $version) {
|
static function get_version($class, $id, $version) {
|
||||||
$oldMode = Versioned::get_reading_mode();
|
$baseClass = ClassInfo::baseDataClass($class);
|
||||||
Versioned::set_reading_mode('');
|
$list = DataList::create($class)->filter("\"$baseClass\".\"RecordID\" = $id")->filter("\"$baseClass\".\"Version\" = " . (int)$version);
|
||||||
|
$list->dataQuery()->setQueryParam('Versioned.mode', 'all_versions');
|
||||||
$baseTable = ClassInfo::baseDataClass($class);
|
return $list->First();
|
||||||
$query = singleton($class)->buildVersionSQL("\"{$baseTable}\".\"RecordID\" = $id AND \"{$baseTable}\".\"Version\" = $version");
|
|
||||||
$record = $query->execute()->record();
|
|
||||||
$className = $record['ClassName'];
|
|
||||||
if(!$className) {
|
|
||||||
Debug::show($query->sql());
|
|
||||||
Debug::show($record);
|
|
||||||
user_error("Versioned::get_version: Couldn't get $class.$id, version $version", E_USER_ERROR);
|
|
||||||
}
|
|
||||||
|
|
||||||
Versioned::set_reading_mode($oldMode);
|
|
||||||
return new $className($record);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return DataObject
|
* Return a list of all versions for a given id
|
||||||
|
* @return DataList
|
||||||
*/
|
*/
|
||||||
static function get_all_versions($class, $id, $version) {
|
static function get_all_versions($class, $id) {
|
||||||
$baseTable = ClassInfo::baseDataClass($class);
|
$baseClass = ClassInfo::baseDataClass($class);
|
||||||
$query = singleton($class)->buildVersionSQL("\"{$baseTable}\".\"RecordID\" = $id AND \"{$baseTable}\".\"Version\" = $version");
|
$list = DataList::create($class)->filter("\"$baseClass\".\"RecordID\" = $id");
|
||||||
$record = $query->execute()->record();
|
$list->dataQuery()->setQueryParam('Versioned.mode', 'all_versions');
|
||||||
$className = $record['ClassName'];
|
return $list;
|
||||||
if(!$className) {
|
|
||||||
Debug::show($query->sql());
|
|
||||||
Debug::show($record);
|
|
||||||
user_error("Versioned::get_version: Couldn't get $class.$id, version $version", E_USER_ERROR);
|
|
||||||
}
|
|
||||||
return new $className($record);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function contentcontrollerInit($controller) {
|
function contentcontrollerInit($controller) {
|
||||||
@ -1070,7 +1015,7 @@ class Versioned extends DataExtension {
|
|||||||
* Return a piece of text to keep DataObject cache keys appropriately specific
|
* Return a piece of text to keep DataObject cache keys appropriately specific
|
||||||
*/
|
*/
|
||||||
function cacheKeyComponent() {
|
function cacheKeyComponent() {
|
||||||
return 'stage-'.self::current_stage();
|
return 'versionedmode-'.self::get_reading_mode();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user