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