xref: /plugin/structpublish/meta/Revision.php (revision c4618b6c6265ede1d9a027588363ed678b625ef7)
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