1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141
<?php
/*-----8<--------------------------------------------------------------------
*
* BEdita - a semantic content management framework
*
* Copyright 2010 ChannelWeb Srl, Chialab Srl
*
* This file is part of BEdita: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
* BEdita is distributed WITHOUT ANY WARRANTY; without even the implied
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
* You should have received a copy of the GNU Lesser General Public License
* version 3 along with BEdita (see LICENSE.LGPL).
* If not, see <http://gnu.org/licenses/lgpl-3.0.html>.
*
*------------------------------------------------------------------->8-----
*/
/**
* Version object
*
* @version $Revision$
* @modifiedby $LastChangedBy$
* @lastmodified $LastChangedDate$
*
* $Id$
*/
class Version extends BEAppModel
{
/**
* fields not versioned/revisioned
*
* @var array
*/
private $noRevision = array("user_modified");
public $belongsTo = array("User");
/**
* Create a new revision, creating a 'diff' between two object data arrays
* and saving a new record in 'versions'
*
* @param array $oldData
* @param array $newData
*/
public function addRevision(array& $oldData, array& $newData) {
$vData = array("object_id" => $oldData["id"],
"created" => $oldData["modified"],
"user_id" => $oldData["user_modified"]);
$lastRev = $this->field("revision", array("object_id" => $vData["object_id"]),
"revision desc");
if(empty($lastRev)) {
$vData["revision"] = 1;
} else {
$vData["revision"] = $lastRev + 1;
}
$diff = $this->calcDiff($oldData, $newData);
if(!empty($diff)) {
$vData["diff"] = serialize($diff);
$this->create();
$this->save($vData);
}
}
private function calcDiff(array& $old, array &$new) {
$newDiff = array_diff_assoc($new, $old);
// remove relations, keep only old object fields/attribs
$diff = array();
foreach ($newDiff as $k => $v) {
if(!is_array($v) && !in_array($k, $this->noRevision)) {
$diff[$k] = !empty($old[$k]) ? $old[$k] : null;
}
}
return $diff;
}
/**
* Create a diff array containing only changed fields between last version
* and requested revision
*
* @param int $id, object id
* @param int $revNum, revision number requested
* @return array with revision information,
*
*/
public function diffData($id, $revNum) {
// check $revNum
$r = $this->field("revision", array("object_id" => $id,
"revision" => $revNum));
if(empty($r)) {
throw new BeditaException(__("Requeste revision not found"));
}
$diffs = $this->find("all", array("conditions" =>
array("Version.object_id" => $id, "Version.revision >= $revNum"),
"fields" => array("diff"), "order" => "Version.revision desc"));
$res = array();
foreach ($diffs as $d) {
$rd = unserialize($d["Version"]["diff"]);
$res = array_merge($res, $rd);
}
return $res;
}
/**
* Return revision data for a specified model, by id and revision number
*
* @param int $id
* @param int $revNum
* @param BEAppModel $model
* @return array
*/
public function revisionData($id, $revNum, BEAppModel $model) {
$model->containLevel('minimum');
$currData = $model->findById($id);
foreach ($currData as $k => $v) {
if(is_array($v)) {
unset($currData[$k]);
}
}
$diff = $this->diffData($id, $revNum);
return array_merge($currData, $diff);
}
/**
* Return number of revisions for specified object id
*
* @param int $id
* @return int
*/
public function numRevisions($id) {
$count = $this->find("count", array(
"conditions" => array("Version.object_id" => $id)
)
);
return $count;
}
}
?>