xref: /dokuwiki/inc/Draft.php (revision f90148d34a91c706a0028485431212698fcf8cc6)
1<?php
2
3namespace dokuwiki;
4
5use dokuwiki\Extension\Event;
6/**
7 * Class Draft
8 *
9 * @package dokuwiki
10 */
11class Draft
12{
13
14    protected $errors = [];
15    protected $cname;
16    protected $id;
17    protected $client;
18
19    /**
20     * Draft constructor.
21     *
22     * @param string $ID the page id for this draft
23     * @param string $client the client identification (username or ip or similar) for this draft
24     */
25    public function __construct($ID, $client)
26    {
27        $this->id = $ID;
28        $this->client = $client;
29        $this->cname = getCacheName("$client\n$ID", '.draft');
30        if(file_exists($this->cname) && file_exists(wikiFN($ID))) {
31            if (filemtime($this->cname) < filemtime(wikiFN($ID))) {
32                // remove stale draft
33                $this->deleteDraft();
34            }
35        }
36    }
37
38    /**
39     * Get the filename for this draft (whether or not it exists)
40     *
41     * @return string
42     */
43    public function getDraftFilename()
44    {
45        return $this->cname;
46    }
47
48    /**
49     * Checks if this draft exists on the filesystem
50     *
51     * @return bool
52     */
53    public function isDraftAvailable()
54    {
55        return file_exists($this->cname);
56    }
57
58    /**
59     * Save a draft of a current edit session
60     *
61     * The draft will not be saved if
62     *   - drafts are deactivated in the config
63     *   - or the editarea is empty and there are no event handlers registered
64     *   - or the event is prevented
65     *
66     * @triggers DRAFT_SAVE
67     *
68     * @return bool whether has the draft been saved
69     */
70    public function saveDraft()
71    {
72        global $INPUT, $INFO, $EVENT_HANDLER, $conf;
73        if (!$conf['usedraft']) {
74            return false;
75        }
76        if (!$INPUT->post->has('wikitext') &&
77            !$EVENT_HANDLER->hasHandlerForEvent('DRAFT_SAVE')) {
78            return false;
79        }
80        $draft = [
81            'id' => $this->id,
82            'prefix' => substr($INPUT->post->str('prefix'), 0, -1),
83            'text' => $INPUT->post->str('wikitext'),
84            'suffix' => $INPUT->post->str('suffix'),
85            'date' => $INPUT->post->int('date'),
86            'client' => $this->client,
87            'cname' => $this->cname,
88            'errors' => [],
89        ];
90        $event = new Event('DRAFT_SAVE', $draft);
91        if ($event->advise_before()) {
92            $draft['hasBeenSaved'] = io_saveFile($draft['cname'], serialize($draft));
93            if ($draft['hasBeenSaved']) {
94                $INFO['draft'] = $draft['cname'];
95            }
96        } else {
97            $draft['hasBeenSaved'] = false;
98        }
99        $event->advise_after();
100
101        $this->errors = $draft['errors'];
102
103        return $draft['hasBeenSaved'];
104    }
105
106    /**
107     * Get the text from the draft file
108     *
109     * @throws \RuntimeException if the draft file doesn't exist
110     *
111     * @return string
112     */
113    public function getDraftText()
114    {
115        if (!file_exists($this->cname)) {
116            throw new \RuntimeException(
117                "Draft for page $this->id and user $this->client doesn't exist at $this->cname."
118            );
119        }
120        $draft = unserialize(io_readFile($this->cname,false));
121        return cleanText(con($draft['prefix'],$draft['text'],$draft['suffix'],true));
122    }
123
124    /**
125     * Remove the draft from the filesystem
126     *
127     * Also sets $INFO['draft'] to null
128     */
129    public function deleteDraft()
130    {
131        global $INFO;
132        @unlink($this->cname);
133        $INFO['draft'] = null;
134    }
135
136    /**
137     * Get a formatted message stating when the draft was saved
138     *
139     * @return string
140     */
141    public function getDraftMessage()
142    {
143        global $lang;
144        return $lang['draftdate'] . ' ' . dformat(filemtime($this->cname));
145    }
146
147    /**
148     * Retrieve the errors that occured when saving the draft
149     *
150     * @return array
151     */
152    public function getErrors()
153    {
154        return $this->errors;
155    }
156
157    /**
158     * Get the timestamp when this draft was saved
159     *
160     * @return int
161     */
162    public function getDraftDate()
163    {
164        return filemtime($this->cname);
165    }
166}
167