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