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 } 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 * @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 * @see https://www.dokuwiki.org/plugin:struct:filters 234 * 235 * @param array $andFilters 236 * @return array|Value[] 237 */ 238 public function getCoreData($andFilters = []) 239 { 240 $lines = [ 241 'schema: structpublish', 242 'cols: *', 243 'sort: revision', 244 'filter: %pageid% = $ID$' 245 ]; 246 247 if (!empty($andFilters)) { 248 foreach ($andFilters as $filter) 249 $lines[] = 'filter: ' . $filter; 250 } 251 252 $parser = new ConfigParser($lines); 253 $config = $parser->getConfig(); 254 $search = new SearchConfig($config); 255 $data = $search->execute(); 256 if (!empty($data)) { 257 return array_pop($data); 258 } 259 return []; 260 } 261 262 /** 263 * Return "latest" published revision of a given page. 264 * If $rev is specified, "latest" means relative to the $rev revision. 265 * 266 * @param int|null $rev 267 * @return Revision|null 268 */ 269 public function getLatestPublishedRevision($rev = null) 270 { 271 $andFilters[] = 'status=' . Constants::STATUS_PUBLISHED; 272 if ($rev) { 273 $andFilters[] .= 'revision<' . $rev; 274 } 275 $latestPublished = $this->getCoreData($andFilters); 276 277 if (empty($latestPublished)) { 278 return null; 279 } 280 281 $published = new Revision($this->sqlite, $this->id, 282 $latestPublished[$this->revisionCol->getColref() - 1]->getRawValue()); 283 284 $published->setStatus($latestPublished[$this->statusCol->getColref() - 1]->getRawValue()); 285 $published->setUser($latestPublished[$this->userCol->getColref() - 1]->getRawValue()); 286 $published->setDatetime($latestPublished[$this->datetimeCol->getColref() - 1]->getRawValue()); 287 $published->setVersion($latestPublished[$this->versionCol->getColref() - 1]->getRawValue()); 288 289 return $published; 290 } 291} 292