1<?php 2 3namespace dokuwiki; 4 5use dokuwiki\Extension\Event; 6 7/** 8 * Class Draft 9 * 10 * @package dokuwiki 11 */ 12class Draft 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 ( 77 !$INPUT->post->has('wikitext') && 78 !$EVENT_HANDLER->hasHandlerForEvent('DRAFT_SAVE') 79 ) { 80 return false; 81 } 82 $draft = [ 83 'id' => $this->id, 84 'prefix' => substr($INPUT->post->str('prefix'), 0, -1), 85 'text' => $INPUT->post->str('wikitext'), 86 'suffix' => $INPUT->post->str('suffix'), 87 'date' => $INPUT->post->int('date'), 88 'client' => $this->client, 89 'cname' => $this->cname, 90 'errors' => [], 91 ]; 92 $event = new Event('DRAFT_SAVE', $draft); 93 if ($event->advise_before()) { 94 $draft['hasBeenSaved'] = io_saveFile($draft['cname'], serialize($draft)); 95 if ($draft['hasBeenSaved']) { 96 $INFO['draft'] = $draft['cname']; 97 } 98 } else { 99 $draft['hasBeenSaved'] = false; 100 } 101 $event->advise_after(); 102 103 $this->errors = $draft['errors']; 104 105 return $draft['hasBeenSaved']; 106 } 107 108 /** 109 * Get the text from the draft file 110 * 111 * @throws \RuntimeException if the draft file doesn't exist 112 * 113 * @return string 114 */ 115 public function getDraftText() 116 { 117 if (!file_exists($this->cname)) { 118 throw new \RuntimeException( 119 "Draft for page $this->id and user $this->client doesn't exist at $this->cname." 120 ); 121 } 122 $draft = unserialize(io_readFile($this->cname, false)); 123 return cleanText(con($draft['prefix'], $draft['text'], $draft['suffix'], true)); 124 } 125 126 /** 127 * Remove the draft from the filesystem 128 * 129 * Also sets $INFO['draft'] to null 130 */ 131 public function deleteDraft() 132 { 133 global $INFO; 134 @unlink($this->cname); 135 $INFO['draft'] = null; 136 } 137 138 /** 139 * Get a formatted message stating when the draft was saved 140 * 141 * @return string 142 */ 143 public function getDraftMessage() 144 { 145 global $lang; 146 return $lang['draftdate'] . ' ' . dformat(filemtime($this->cname)); 147 } 148 149 /** 150 * Retrieve the errors that occured when saving the draft 151 * 152 * @return array 153 */ 154 public function getErrors() 155 { 156 return $this->errors; 157 } 158 159 /** 160 * Get the timestamp when this draft was saved 161 * 162 * @return int 163 */ 164 public function getDraftDate() 165 { 166 return filemtime($this->cname); 167 } 168} 169