1<?php 2 3namespace dokuwiki\plugin\structpublish\meta; 4 5use dokuwiki\plugin\struct\meta\Column; 6use dokuwiki\plugin\sqlite\SQLiteDB; 7use dokuwiki\plugin\struct\meta\ConfigParser; 8use dokuwiki\plugin\struct\meta\Schema; 9use dokuwiki\plugin\struct\meta\SearchConfig; 10use dokuwiki\plugin\struct\meta\Value; 11 12/** 13 * Object representing a page revision and its properties 14 */ 15class Revision 16{ 17 /** @var SQLiteDB */ 18 protected $sqlite; 19 20 protected $schema; 21 22 protected $id; 23 protected $rev; 24 protected $published = 0; 25 protected $status = Constants::STATUS_DRAFT; 26 protected $version; 27 protected $user; 28 protected $datetime; 29 /** @var bool|Column */ 30 protected $statusCol; 31 protected $versionCol; 32 protected $userCol; 33 protected $datetimeCol; 34 protected $revisionCol; 35 36 /** 37 * Constructor 38 * 39 * @param string $id page id 40 * @param int $rev revision 41 */ 42 public function __construct($id, $rev) 43 { 44 $this->id = $id; 45 $this->rev = $rev; 46 47 $this->schema = new Schema('structpublish'); 48 $this->statusCol = $this->schema->findColumn('status'); 49 $this->versionCol = $this->schema->findColumn('version'); 50 $this->userCol = $this->schema->findColumn('user'); 51 $this->datetimeCol = $this->schema->findColumn('datetime'); 52 $this->revisionCol = $this->schema->findColumn('revision'); 53 54 /** @var Value[] $values */ 55 $values = $this->getCoreData(['revision=' . $this->rev]); 56 57 if (!empty($values)) { 58 $this->status = $values[$this->statusCol->getColref() - 1]->getRawValue(); 59 $this->version = $values[$this->versionCol->getColref() - 1]->getRawValue(); 60 $this->user = $values[$this->userCol->getColref() - 1]->getRawValue(); 61 $this->datetime = $values[$this->datetimeCol->getColref() - 1]->getRawValue(); 62 } 63 } 64 65 /** 66 * Store the currently set structpublish meta data in the database 67 * 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 * 201 * @return string 202 */ 203 public function getId() 204 { 205 return $this->id; 206 } 207 208 /** 209 * Update publish status in the core table 210 * 211 * @param string $pid 212 * @param int $rid 213 */ 214 protected function updateCoreData($pid, $rid = 0) 215 { 216 $data = [ 217 'status' => $this->status, 218 'user' => $this->user, 219 'datetime' => $this->datetime, 220 'revision' => $this->rev, 221 'version' => $this->version, 222 ]; 223 $schema = new Schema('structpublish', 0); 224 $access = new AccessTableStructpublish($schema, $pid, 0, $rid); 225 $access->setPublished($this->published); 226 $access->saveData($data); 227 } 228 229 /** 230 * Fetches data from the structpublish schema for the current page. 231 * Returns an array of struct Value objects, not literal values. 232 * $andFilters can be used to limit the search, e.g. by status or revision 233 * 234 * @see https://www.dokuwiki.org/plugin:struct:filters 235 * 236 * @param array $andFilters 237 * @return array|Value[] 238 */ 239 public function getCoreData($andFilters = []) 240 { 241 $lines = [ 242 'schema: structpublish', 243 'cols: *', 244 'sort: revision', 245 'filter: %pageid% = $ID$' 246 ]; 247 248 if (!empty($andFilters)) { 249 foreach ($andFilters as $filter) { 250 $lines[] = 'filter: ' . $filter; 251 } 252 } 253 254 $parser = new ConfigParser($lines); 255 $config = $parser->getConfig(); 256 $search = new SearchConfig($config); 257 // disable 'latest' flag in select query 258 $search->setSelectLatest(false); 259 260 $data = $search->getRows(); 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