depage-xmldb v2.3.1
XML documents in a relational database
Loading...
Searching...
No Matches
DocumentHistory.php
Go to the documentation of this file.
1<?php
2
12
13namespace Depage\XmlDb;
14
16{
17 private $pdo;
18 private $dbNs;
19 private $tableHistory;
20
21 private $document;
22 private $dateFormat = 'Y-m-d H:i:s';
23 public function __construct(\Depage\Db\Pdo $pdo, $tablePrefix, Document $document)
24 {
25 $this->document = $document;
26
27 $this->pdo = $pdo;
28
29 $this->dbNs = new XmlNs('db', 'http://cms.depagecms.net/ns/database');
30
31 $this->tableHistory = $tablePrefix . '_history';
32 }
33
45 public function getVersions($published = null, $maxResults = null)
46 {
47 $query = "SELECT h.hash, h.last_saved_at, h.first_saved_at, h.user_id, h.published
48 FROM {$this->tableHistory} AS h
49 WHERE h.doc_id = :doc_id";
50
51 $params = [
52 'doc_id' => $this->document->getDocId(),
53 ];
54
55 if ($published !== null) {
56 $query .= ' AND h.published = :published';
57 $params['published'] = $published ? 1 : 0;
58 }
59
60 $query .= ' ORDER BY h.last_saved_at DESC';
61
62 if ($maxResults > 0) {
63 $query .= ' LIMIT :maxResults';
64 $params['maxResults'] = $maxResults;
65 }
66
67 $query .= ';';
68
69 $sth = $this->pdo->prepare($query);
70
71 $versions = [];
72
73 if ($sth->execute($params)) {
74 $results = $sth->fetchAll();
75
76 foreach ($results as &$result) {
77 $versions[strtotime($result['last_saved_at'])] = (object) [
78 'firstsaved' => new \DateTime($result['first_saved_at']),
79 'lastsaved' => new \DateTime($result['last_saved_at']),
80 'userId' => $result['user_id'],
81 'published' => $result['published'],
82 'hash' => $result['hash'],
83 ];
84 }
85 }
86
87 return $versions;
88 }
89
94 public function getLatestVersion()
95 {
96 $versions = $this->getVersions(true, 1);
97
98 return reset($versions);
99 }
100
108 public function getXml($timestamp, $addIdAttribute = true)
109 {
110 $doc = false;
111 $docId = $this->document->getDocId();
112
113 $query = $this->pdo->prepare(
114 "SELECT
115 h.xml,
116 h.last_saved_at as lastchange,
117 h.user_id as uid
118 FROM {$this->tableHistory} AS h
119 WHERE h.doc_id = :doc_id
120 AND h.last_saved_at <= :timestamp
121 ORDER BY h.last_saved_at DESC
122 LIMIT 1"
123 );
124
125 $params = [
126 'doc_id' => $docId,
127 'timestamp' => date($this->dateFormat, $timestamp),
128 ];
129
130 if ($query->execute($params) && $result = $query->fetchObject()) {
131 $doc = new \Depage\Xml\Document();
132 $doc->loadXML($result->xml);
133 if (!$addIdAttribute) {
134 Document::removeNodeAttr($doc, $this->dbNs, 'id');
135 }
136 $doc->documentElement->setAttribute('db:docid', $docId);
137 $doc->documentElement->setAttribute('db:lastchange', $result->lastchange);
138 }
139
140 return $doc;
141 }
142
147 public function getLastPublishedXml($addIdAttribute = true)
148 {
149 $versions = $this->getVersions(true, 1);
150 reset($versions);
151 $latest = key($versions);
152
153 return $this->getXml($latest, $addIdAttribute);
154 }
155
165 public function save($userId, $published = false)
166 {
167 $result = false;
168 $timestamp = time();
169
170 $doc = $this->document->getXml();
171 $dth = $this->document->getDoctypeHandler();
172 Document::removeNodeAttr($doc, $this->dbNs, 'lastchange');
173 Document::removeNodeAttr($doc, $this->dbNs, 'docid');
174
175 $dth->testDocumentForHistory($doc);
176
177 $xml = $doc->saveXml();
178 $hash = $this->document->hashDomNode($doc);
179
180 $latestVersion = $this->getLatestVersion();
181
182 if (!$latestVersion || $latestVersion->hash != $hash) {
183 // insert new version into history
184 $query = $this->pdo->prepare(
185 "INSERT INTO {$this->tableHistory} (doc_id, hash, xml, first_saved_at, last_saved_at, user_id, published)
186 VALUES(:doc_id, :hash, :xml, :timestamp1, :timestamp2, :user_id, :published);"
187 );
188
189 $params = [
190 'doc_id' => $this->document->getDocId(),
191 'hash' => $hash,
192 'xml' => $xml,
193 'timestamp1' => date($this->dateFormat, $timestamp),
194 'timestamp2' => date($this->dateFormat, $timestamp),
195 'user_id' => $userId,
196 'published' => $published ? 1 : 0,
197 ];
198
199 $query->execute($params);
200 $dth->onHistorySave();
201 } else {
202 // update date of latest version
203 $query = $this->pdo->prepare(
204 "UPDATE {$this->tableHistory}
205 SET last_saved_at = :timestamp
206 WHERE
207 doc_id = :doc_id AND
208 hash = :hash
209 ;"
210 );
211
212 $params = [
213 'doc_id' => $this->document->getDocId(),
214 'hash' => $hash,
215 'timestamp' => date($this->dateFormat, $timestamp),
216 ];
217
218 $query->execute($params);
219 }
220
221 // the release state reported in getDocInfo is derived from the
222 // history, drop the memoized info
223 $this->document->clearDocInfoCache();
224
225 $result = $timestamp;
226
227 return $result;
228 }
229
232 public function restore($timestamp)
233 {
234 $success = false;
235 $xmlDoc = $this->getXml($timestamp);
236
237 if ($this->document->save($xmlDoc)) {
238 $success = $xmlDoc;
239 }
240
241 return $success;
242 }
243
248 public function delete($timestamp)
249 {
250 $query = $this->pdo->prepare(
251 "DELETE FROM {$this->tableHistory}
252 WHERE doc_id = :doc_id AND last_saved_at = :timestamp;"
253 );
254
255 $params = [
256 'doc_id' => $this->document->getDocId(),
257 'timestamp' => date($this->dateFormat, $timestamp),
258 ];
259
260 if ($query->execute($params)) {
261 // deleting a version may change the release state reported
262 // in getDocInfo, drop the memoized info
263 $this->document->clearDocInfoCache();
264
265 return $query->rowCount() > 0;
266 }
267
268 return false;
269 }
270}
271
272/* vim:set ft=php sw=4 sts=4 fdm=marker et : */
getLastPublishedXml($addIdAttribute=true)
getLastPublishedXml
getLatestVersion()
getLatestVersion
getXml($timestamp, $addIdAttribute=true)
getXml
save($userId, $published=false)
gets the current document xml and saves a version to the history add SHA hash column for data integri...
__construct(\Depage\Db\Pdo $pdo, $tablePrefix, Document $document)
getVersions($published=null, $maxResults=null)
getVersions
restore($timestamp)
Restores the document to a previous state.
static removeNodeAttr($node, $dbNs, $attribute)
recursively remove attributes from node
A namespace prefix and the URI it is bound to.
Definition XmlNs.php:9