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