Skip to content

Commit

Permalink
Merge pull request #2415 from splitbrain/betterDraftHandling
Browse files Browse the repository at this point in the history
Better draft handling
  • Loading branch information
splitbrain committed Jun 14, 2018
2 parents d4a8e67 + e432cc8 commit 69a81ab
Show file tree
Hide file tree
Showing 8 changed files with 245 additions and 72 deletions.
12 changes: 7 additions & 5 deletions inc/Action/Draftdel.php
Expand Up @@ -19,16 +19,18 @@ public function minimumPermission() {
}

/**
* Delete an existing draft if any
* Delete an existing draft for the current page and user if any
*
* Reads draft information from $INFO. Redirects to show, afterwards.
* Redirects to show, afterwards.
*
* @throws ActionAbort
*/
public function preProcess() {
global $INFO;
@unlink($INFO['draft']);
$INFO['draft'] = null;
global $INFO, $ID;
$draft = new \dokuwiki\Draft($ID, $INFO['client']);
if ($draft->isDraftAvailable()) {
$draft->deleteDraft();
}

throw new ActionAbort('redirect');
}
Expand Down
30 changes: 7 additions & 23 deletions inc/Action/Preview.php
Expand Up @@ -29,29 +29,13 @@ public function tplContent() {
* Saves a draft on preview
*/
protected function savedraft() {
global $INFO;
global $ID;
global $INPUT;
global $conf;

if(!$conf['usedraft']) return;
if(!$INPUT->post->has('wikitext')) return;

// ensure environment (safeguard when used via AJAX)
assert(isset($INFO['client']), 'INFO.client should have been set');
assert(isset($ID), 'ID should have been set');

$draft = array(
'id' => $ID,
'prefix' => substr($INPUT->post->str('prefix'), 0, -1),
'text' => $INPUT->post->str('wikitext'),
'suffix' => $INPUT->post->str('suffix'),
'date' => $INPUT->post->int('date'),
'client' => $INFO['client'],
);
$cname = getCacheName($draft['client'] . $ID, '.draft');
if(io_saveFile($cname, serialize($draft))) {
$INFO['draft'] = $cname;
global $ID, $INFO;
$draft = new \dokuwiki\Draft($ID, $INFO['client']);
if (!$draft->saveDraft()) {
$errors = $draft->getErrors();
foreach ($errors as $error) {
msg(hsc($error), -1);
}
}
}

Expand Down
35 changes: 14 additions & 21 deletions inc/Ajax.php
Expand Up @@ -119,8 +119,6 @@ protected function call_suggestions() {
* Andreas Gohr <andi@splitbrain.org>
*/
protected function call_lock() {
global $conf;
global $lang;
global $ID;
global $INFO;
global $INPUT;
Expand All @@ -130,34 +128,29 @@ protected function call_lock() {

$INFO = pageinfo();

$response = [
'errors' => [],
'lock' => '0',
'draft' => '',
];
if(!$INFO['writable']) {
echo 'Permission denied';
$response['errors'][] = 'Permission to write this page has been denied.';
echo json_encode($response);
return;
}

if(!checklock($ID)) {
lock($ID);
echo 1;
$response['lock'] = '1';
}

if($conf['usedraft'] && $INPUT->post->str('wikitext')) {
$client = $_SERVER['REMOTE_USER'];
if(!$client) $client = clientIP(true);

$draft = array(
'id' => $ID,
'prefix' => substr($INPUT->post->str('prefix'), 0, -1),
'text' => $INPUT->post->str('wikitext'),
'suffix' => $INPUT->post->str('suffix'),
'date' => $INPUT->post->int('date'),
'client' => $client,
);
$cname = getCacheName($draft['client'] . $ID, '.draft');
if(io_saveFile($cname, serialize($draft))) {
echo $lang['draftdate'] . ' ' . dformat();
}
$draft = new Draft($ID, $INFO['client']);
if ($draft->saveDraft()) {
$response['draft'] = $draft->getDraftMessage();
} else {
$response['errors'] = array_merge($response['errors'], $draft->getErrors());
}

echo json_encode($response);
}

/**
Expand Down
155 changes: 155 additions & 0 deletions inc/Draft.php
@@ -0,0 +1,155 @@
<?php

namespace dokuwiki;

/**
* Class Draft
*
* @package dokuwiki
*/
class Draft
{

protected $errors = [];
protected $cname;
protected $id;
protected $client;

/**
* Draft constructor.
*
* @param string $ID the page id for this draft
* @param string $client the client identification (username or ip or similar) for this draft
*/
public function __construct($ID, $client)
{
$this->id = $ID;
$this->client = $client;
$this->cname = getCacheName($client.$ID, '.draft');
if(file_exists($this->cname) && file_exists(wikiFN($ID))) {
if (filemtime($this->cname) < filemtime(wikiFN($ID))) {
// remove stale draft
$this->deleteDraft();
}
}
}

/**
* Get the filename for this draft (whether or not it exists)
*
* @return string
*/
public function getDraftFilename()
{
return $this->cname;
}

/**
* Checks if this draft exists on the filesystem
*
* @return bool
*/
public function isDraftAvailable()
{
return file_exists($this->cname);
}

/**
* Save a draft of a current edit session
*
* The draft will not be saved if
* - drafts are deactivated in the config
* - or the editarea is empty and there are no event handlers registered
* - or the event is prevented
*
* @triggers DRAFT_SAVE
*
* @return bool whether has the draft been saved
*/
public function saveDraft()
{
global $INPUT, $INFO, $EVENT_HANDLER, $conf;
if (!$conf['usedraft']) {
return false;
}
if (!$INPUT->post->has('wikitext') &&
!$EVENT_HANDLER->hasHandlerForEvent('DRAFT_SAVE')) {
return false;
}
$draft = [
'id' => $this->id,
'prefix' => substr($INPUT->post->str('prefix'), 0, -1),
'text' => $INPUT->post->str('wikitext'),
'suffix' => $INPUT->post->str('suffix'),
'date' => $INPUT->post->int('date'),
'client' => $this->client,
'cname' => $this->cname,
'errors' => [],
];
$event = new \Doku_Event('DRAFT_SAVE', $draft);
if ($event->advise_before()) {
$draft['hasBeenSaved'] = io_saveFile($draft['cname'], serialize($draft));
if ($draft['hasBeenSaved']) {
$INFO['draft'] = $draft['cname'];
}
} else {
$draft['hasBeenSaved'] = false;
}
$event->advise_after();

$this->errors = $draft['errors'];

return $draft['hasBeenSaved'];
}

/**
* Get the text from the draft file
*
* @throws \RuntimeException if the draft file doesn't exist
*
* @return string
*/
public function getDraftText()
{
if (!file_exists($this->cname)) {
throw new \RuntimeException(
"Draft for page $this->id and user $this->client doesn't exist at $this->cname."
);
}
$draft = unserialize(io_readFile($this->cname,false));
return cleanText(con($draft['prefix'],$draft['text'],$draft['suffix'],true));
}

/**
* Remove the draft from the filesystem
*
* Also sets $INFO['draft'] to null
*/
public function deleteDraft()
{
global $INFO;
@unlink($this->cname);
$INFO['draft'] = null;
}

/**
* Get a formatted message stating when the draft was saved
*
* @return string
*/
public function getDraftMessage()
{
global $lang;
return $lang['draftdate'] . ' ' . dformat(filemtime($this->cname));
}

/**
* Retrieve the errors that occured when saving the draft
*
* @return array
*/
public function getErrors()
{
return $this->errors;
}
}
11 changes: 3 additions & 8 deletions inc/common.php
Expand Up @@ -287,14 +287,9 @@ function pageinfo() {
}

// draft
$draft = getCacheName($info['client'].$ID, '.draft');
if(file_exists($draft)) {
if(@filemtime($draft) < @filemtime(wikiFN($ID))) {
// remove stale draft
@unlink($draft);
} else {
$info['draft'] = $draft;
}
$draft = new \dokuwiki\Draft($ID, $info['client']);
if ($draft->isDraftAvailable()) {
$info['draft'] = $draft->getDraftFilename();
}

return $info;
Expand Down
13 changes: 10 additions & 3 deletions inc/html.php
Expand Up @@ -307,8 +307,8 @@ function html_draft(){
global $INFO;
global $ID;
global $lang;
$draft = unserialize(io_readFile($INFO['draft'],false));
$text = cleanText(con($draft['prefix'],$draft['text'],$draft['suffix'],true));
$draft = new \dokuwiki\Draft($ID, $INFO['client']);
$text = $draft->getDraftText();

print p_locale_xhtml('draft');
html_diff($text, false);
Expand Down Expand Up @@ -1833,10 +1833,17 @@ function html_edit(){
<div class="editBox" role="application">

<div class="toolbar group">
<div id="draft__status" class="draft__status"><?php if(!empty($INFO['draft'])) echo $lang['draftdate'].' '.dformat();?></div>
<div id="tool__bar" class="tool__bar"><?php if ($wr && $data['media_manager']){?><a href="<?php echo DOKU_BASE?>lib/exe/mediamanager.php?ns=<?php echo $INFO['namespace']?>"
target="_blank"><?php echo $lang['mediaselect'] ?></a><?php }?></div>
</div>
<div id="draft__status" class="draft__status">
<?php
$draft = new \dokuwiki\Draft($ID, $INFO['client']);
if ($draft->isDraftAvailable()) {
echo $draft->getDraftMessage();
}
?>
</div>
<?php

html_form('edit', $form);
Expand Down

0 comments on commit 69a81ab

Please sign in to comment.