1<?php 2 3namespace dokuwiki\plugin\structpublish\meta; 4 5use dokuwiki\plugin\struct\meta\ConfigParser; 6use dokuwiki\plugin\struct\meta\Schema; 7use dokuwiki\plugin\struct\meta\SearchConfig; 8use dokuwiki\plugin\struct\meta\Value; 9 10/** 11 * Object representing a page revision and its properties 12 */ 13class Revision 14{ 15 /** @var \helper_plugin_sqlite */ 16 protected $sqlite; 17 18 protected $schema; 19 20 protected $id; 21 protected $rev; 22 protected $published; 23 protected $status; 24 protected $version; 25 protected $user; 26 protected $datetime; 27 /** @var bool|\dokuwiki\plugin\struct\meta\Column */ 28 protected $statusCol; 29 protected $versionCol; 30 protected $userCol; 31 protected $datetimeCol; 32 protected $revisionCol; 33 34 /** 35 * Constructor 36 * 37 * @param \helper_plugin_sqlite $sqlite 38 * @param string $id page id 39 * @param int $rev revision 40 */ 41 public function __construct($sqlite, $id, $rev) 42 { 43 $this->sqlite = $sqlite; 44 $this->id = $id; 45 $this->rev = $rev; 46 $this->published = 0; 47 $this->status = Constants::STATUS_DRAFT; 48 49 $this->schema = new Schema('structpublish'); 50 $this->statusCol = $this->schema->findColumn('status'); 51 $this->versionCol = $this->schema->findColumn('version'); 52 $this->userCol = $this->schema->findColumn('user'); 53 $this->datetimeCol = $this->schema->findColumn('datetime'); 54 $this->revisionCol = $this->schema->findColumn('revision'); 55 56 /** @var Value[] $values */ 57 $values = $this->getCoreData(['revision=' . $this->rev]); 58 59 if (!empty($values)) { 60 $this->status = $values[$this->statusCol->getColref() - 1]->getRawValue(); 61 $this->version = $values[$this->versionCol->getColref() - 1]->getRawValue(); 62 $this->user = $values[$this->userCol->getColref() - 1]->getRawValue(); 63 $this->datetime = $values[$this->datetimeCol->getColref() - 1]->getRawValue(); 64 } 65 } 66 67 /** 68 * Store the currently set structpublish meta data in the database 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 // TODO reset publish status of older revisions 79 } 80 81 /** 82 * Return the version of a published revision 83 * 84 * @return string|null 85 */ 86 public function getVersion() 87 { 88 return $this->version; 89 } 90 91 /** 92 * Set the version of a published revision 93 * 94 * @param string $version 95 */ 96 public function setVersion($version) 97 { 98 $this->version = $version; 99 } 100 101 /** 102 * The revision timestamp 103 * 104 * @return int 105 */ 106 public function getRev() 107 { 108 return $this->rev; 109 } 110 111 /** 112 * Get the current status of this revision 113 * 114 * @return string 115 */ 116 public function getStatus() 117 { 118 return $this->status; 119 } 120 121 /** 122 * Set the current status of this revision 123 * 124 * @param string $status 125 */ 126 public function setStatus($status) 127 { 128 $this->status = $status; 129 } 130 131 /** 132 * Get the user that changed the status of this revision 133 * 134 * Not available for drafts 135 * 136 * @return string|null 137 */ 138 public function getUser() 139 { 140 return $this->user; 141 } 142 143 /** 144 * Set the user that changed the revision status 145 * 146 * @param string $user 147 */ 148 public function setUser($user): void 149 { 150 $this->user = $user; 151 } 152 153 /** 154 * The datetime when the status of this revision was changed 155 * 156 * Uses ISO Format. Not available for drafts 157 * 158 * @return string|null 159 */ 160 public function getDatetime() 161 { 162 return $this->datetime; 163 } 164 165 /** 166 * The timestamp of when the status of this revision was changed 167 * 168 * Not available for drafts 169 * 170 * @return int|null 171 */ 172 public function getTimestamp() 173 { 174 if ($this->datetime === null) { 175 return null; 176 } 177 return strtotime($this->datetime); 178 } 179 180 /** 181 * Set the datetime when the status of this revision was changed 182 * 183 * Uses ISO Format 184 * 185 * @param string $time 186 */ 187 public function setDatetime($time) 188 { 189 $this->datetime = $time; 190 } 191 192 /** 193 * Set the timestamp of when the status of this revision was changed 194 */ 195 public function setTimestamp($timestamp) 196 { 197 $this->datetime = date('Y-m-d\TH:i', $timestamp); 198 } 199 200 /** 201 * The page ID this revision is for 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 * @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 $parser = new ConfigParser($lines); 254 $config = $parser->getConfig(); 255 $search = new SearchConfig($config); 256 $data = $search->execute(); 257 if (!empty($data)) { 258 return $data[array_key_last($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->sqlite, $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