1<?php 2 3namespace dokuwiki\plugin\structpublish\meta; 4 5use dokuwiki\plugin\sqlite\SQLiteDB; 6use dokuwiki\plugin\struct\meta\ConfigParser; 7use dokuwiki\plugin\struct\meta\Schema; 8use dokuwiki\plugin\struct\meta\SearchConfig; 9use dokuwiki\plugin\struct\meta\Value; 10 11/** 12 * Object representing a page revision and its properties 13 */ 14class Revision 15{ 16 /** @var SQLiteDB */ 17 protected $sqlite; 18 19 protected $schema; 20 21 protected $id; 22 protected $rev; 23 protected $published; 24 protected $status; 25 protected $version; 26 protected $user; 27 protected $datetime; 28 /** @var bool|\dokuwiki\plugin\struct\meta\Column */ 29 protected $statusCol; 30 protected $versionCol; 31 protected $userCol; 32 protected $datetimeCol; 33 protected $revisionCol; 34 35 /** 36 * Constructor 37 * 38 * @param string $id page id 39 * @param int $rev revision 40 */ 41 public function __construct($id, $rev) 42 { 43 $this->id = $id; 44 $this->rev = $rev; 45 $this->published = 0; 46 $this->status = Constants::STATUS_DRAFT; 47 48 $this->schema = new Schema('structpublish'); 49 $this->statusCol = $this->schema->findColumn('status'); 50 $this->versionCol = $this->schema->findColumn('version'); 51 $this->userCol = $this->schema->findColumn('user'); 52 $this->datetimeCol = $this->schema->findColumn('datetime'); 53 $this->revisionCol = $this->schema->findColumn('revision'); 54 55 /** @var Value[] $values */ 56 $values = $this->getCoreData(['revision=' . $this->rev]); 57 58 if (!empty($values)) { 59 $this->status = $values[$this->statusCol->getColref() - 1]->getRawValue(); 60 $this->version = $values[$this->versionCol->getColref() - 1]->getRawValue(); 61 $this->user = $values[$this->userCol->getColref() - 1]->getRawValue(); 62 $this->datetime = $values[$this->datetimeCol->getColref() - 1]->getRawValue(); 63 } 64 } 65 66 /** 67 * Store the currently set structpublish meta data in the database 68 * @return void 69 */ 70 public function save() 71 { 72 if ($this->status === Constants::STATUS_PUBLISHED) { 73 $this->published = 1; 74 } 75 76 $this->updateCoreData($this->id); 77 } 78 79 /** 80 * Return the version of a published revision 81 * 82 * @return string|null 83 */ 84 public function getVersion() 85 { 86 return $this->version; 87 } 88 89 /** 90 * Set the version of a published revision 91 * 92 * @param string $version 93 */ 94 public function setVersion($version) 95 { 96 $this->version = $version; 97 } 98 99 /** 100 * The revision timestamp 101 * 102 * @return int 103 */ 104 public function getRev() 105 { 106 return $this->rev; 107 } 108 109 /** 110 * Get the current status of this revision 111 * 112 * @return string 113 */ 114 public function getStatus() 115 { 116 return $this->status; 117 } 118 119 /** 120 * Set the current status of this revision 121 * 122 * @param string $status 123 */ 124 public function setStatus($status) 125 { 126 $this->status = $status; 127 } 128 129 /** 130 * Get the user that changed the status of this revision 131 * 132 * Not available for drafts 133 * 134 * @return string|null 135 */ 136 public function getUser() 137 { 138 return $this->user; 139 } 140 141 /** 142 * Set the user that changed the revision status 143 * 144 * @param string $user 145 */ 146 public function setUser($user): void 147 { 148 $this->user = $user; 149 } 150 151 /** 152 * The datetime when the status of this revision was changed 153 * 154 * Uses ISO Format. Not available for drafts 155 * 156 * @return string|null 157 */ 158 public function getDatetime() 159 { 160 return $this->datetime; 161 } 162 163 /** 164 * The timestamp of when the status of this revision was changed 165 * 166 * Not available for drafts 167 * 168 * @return int|null 169 */ 170 public function getTimestamp() 171 { 172 if ($this->datetime === null) { 173 return null; 174 } 175 return strtotime($this->datetime); 176 } 177 178 /** 179 * Set the datetime when the status of this revision was changed 180 * 181 * Uses ISO Format 182 * 183 * @param string $time 184 */ 185 public function setDatetime($time) 186 { 187 $this->datetime = $time; 188 } 189 190 /** 191 * Set the timestamp of when the status of this revision was changed 192 */ 193 public function setTimestamp($timestamp) 194 { 195 $this->datetime = date('Y-m-d\TH:i', $timestamp); 196 } 197 198 /** 199 * The page ID this revision is for 200 * @return string 201 */ 202 public function getId() 203 { 204 return $this->id; 205 } 206 207 /** 208 * Update publish status in the core table 209 * 210 * @param string $pid 211 * @param int $rid 212 */ 213 protected function updateCoreData($pid, $rid = 0) 214 { 215 $data = [ 216 'status' => $this->status, 217 'user' => $this->user, 218 'datetime' => $this->datetime, 219 'revision' => $this->rev, 220 'version' => $this->version, 221 ]; 222 $schema = new Schema('structpublish', 0); 223 $access = new AccessTableStructpublish($schema, $pid, 0, $rid); 224 $access->setPublished($this->published); 225 $access->saveData($data); 226 } 227 228 /** 229 * Fetches data from the structpublish schema for the current page. 230 * Returns an array of struct Value objects, not literal values. 231 * $andFilters can be used to limit the search, e.g. by status or revision 232 * @see https://www.dokuwiki.org/plugin:struct:filters 233 * 234 * @param array $andFilters 235 * @return array|Value[] 236 */ 237 public function getCoreData($andFilters = []) 238 { 239 $lines = [ 240 'schema: structpublish', 241 'cols: *', 242 'sort: revision', 243 'filter: %pageid% = $ID$' 244 ]; 245 246 if (!empty($andFilters)) { 247 foreach ($andFilters as $filter) 248 $lines[] = 'filter: ' . $filter; 249 } 250 251 $parser = new ConfigParser($lines); 252 $config = $parser->getConfig(); 253 $search = new SearchConfig($config); 254 // disable 'latest' flag in select query 255 $search->setSelectLatest(false); 256 $data = $search->execute(); 257 if (!empty($data)) { 258 return array_pop($data); 259 } 260 return []; 261 } 262 263 /** 264 * Return "latest" published revision of a given page. 265 * If $rev is specified, "latest" means relative to the $rev revision. 266 * 267 * @param int|null $rev 268 * @return Revision|null 269 */ 270 public function getLatestPublishedRevision($rev = null) 271 { 272 $andFilters[] = 'status=' . Constants::STATUS_PUBLISHED; 273 if ($rev) { 274 $andFilters[] .= 'revision<' . $rev; 275 } 276 $latestPublished = $this->getCoreData($andFilters); 277 278 if (empty($latestPublished)) { 279 return null; 280 } 281 282 $published = new Revision($this->id, 283 $latestPublished[$this->revisionCol->getColref() - 1]->getRawValue()); 284 285 $published->setStatus($latestPublished[$this->statusCol->getColref() - 1]->getRawValue()); 286 $published->setUser($latestPublished[$this->userCol->getColref() - 1]->getRawValue()); 287 $published->setDatetime($latestPublished[$this->datetimeCol->getColref() - 1]->getRawValue()); 288 $published->setVersion($latestPublished[$this->versionCol->getColref() - 1]->getRawValue()); 289 290 return $published; 291 } 292} 293