xref: /plugin/structpublish/meta/Revision.php (revision f1c406c2fa3c90d0ee5b5b06d541451b174b6255)
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 $data[array_key_last($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