From ee4c4a1b5a5840c1b9d2d8c74b3f4298dd52928b Mon Sep 17 00:00:00 2001 From: Andreas Gohr Date: Sat, 11 Mar 2006 21:01:48 +0100 Subject: Automatic draft saving DokuWiki now automatically creates a draft file of the currently edited page. In case of an editing interuption (eg. Browsercrash) the draftfile can be continued later. darcs-hash:20060311200148-7ad00-919337a51e001136178d175a1755cd26122e9726.gz --- inc/actions.php | 77 +++++++++++++++++++++++++++++++++++++++++++++------- inc/common.php | 14 ++++++++++ inc/html.php | 47 ++++++++++++++++++++++++++++---- inc/io.php | 3 ++ inc/lang/en/lang.php | 10 +++++-- inc/template.php | 14 +++++++--- 6 files changed, 142 insertions(+), 23 deletions(-) (limited to 'inc') diff --git a/inc/actions.php b/inc/actions.php index e92e366d0..963be86a9 100644 --- a/inc/actions.php +++ b/inc/actions.php @@ -62,6 +62,14 @@ function act_dispatch(){ if($ACT == 'save') $ACT = act_save($ACT); + //draft deletion + if($ACT == 'draftdel') + $ACT = act_draftdel($ACT); + + //draft saving on preview + if($ACT == 'preview') + $ACT = act_draftsave($ACT); + //edit if(($ACT == 'edit' || $ACT == 'preview') && $INFO['editable']){ $ACT = act_edit($ACT); @@ -116,10 +124,18 @@ function act_clean($act){ global $lang; global $conf; + // check if the action was given as array key + if(is_array($act)){ + list($act) = array_keys($act); + } + //handle localized buttons - if($act == $lang['btn_save']) $act = 'save'; - if($act == $lang['btn_preview']) $act = 'preview'; - if($act == $lang['btn_cancel']) $act = 'show'; + if($act == $lang['btn_save']) $act = 'save'; + if($act == $lang['btn_preview']) $act = 'preview'; + if($act == $lang['btn_cancel']) $act = 'show'; + if($act == $lang['btn_recover']) $act = 'recover'; + if($act == $lang['btn_draftdel']) $act = 'draftdel'; + //remove all bad chars $act = strtolower($act); @@ -136,12 +152,12 @@ function act_clean($act){ return 'show'; } - if(array_search($act,array('login','logout','register','save','edit', - 'preview','search','show','check','index','revisions', - 'diff','recent','backlink','admin','subscribe', - 'unsubscribe','profile','resendpwd',)) === false - && substr($act,0,7) != 'export_' ) { - msg('Unknown command: '.htmlspecialchars($act),-1); + if(!in_array($act,array('login','logout','register','save','edit','draft', + 'preview','search','show','check','index','revisions', + 'diff','recent','backlink','admin','subscribe', + 'unsubscribe','profile','resendpwd','recover', + 'draftdel',)) && substr($act,0,7) != 'export_' ) { + msg('Command unknown: '.htmlspecialchars($act),-1); return 'show'; } return $act; @@ -156,7 +172,7 @@ function act_permcheck($act){ global $INFO; global $conf; - if(in_array($act,array('save','preview','edit'))){ + if(in_array($act,array('save','preview','edit','recover'))){ if($INFO['exists']){ if($act == 'edit'){ //the edit function will check again and do a source show @@ -186,6 +202,43 @@ function act_permcheck($act){ return 'denied'; } +/** + * Handle 'draftdel' + * + * Deletes the draft for the current page and user + */ +function act_draftdel($act){ + global $INFO; + @unlink($INFO['draft']); + $INFO['draft'] = null; + return 'show'; +} + +/** + * Saves a draft on preview + * + * @todo this currently duplicates code from ajax.php :-/ + */ +function act_draftsave($act){ + global $INFO; + global $ID; + global $conf; + if($conf['usedraft'] && $_POST['wikitext']){ + $draft = array('id' => $ID, + 'prefix' => $_POST['prefix'], + 'text' => $_POST['wikitext'], + 'suffix' => $_POST['suffix'], + 'date' => $_POST['date'], + 'client' => $INFO['client'], + ); + $cname = getCacheName($draft['client'].$ID,'.draft'); + if(io_saveFile($cname,serialize($draft))){ + $INFO['draft'] = $cname; + } + } + return $act; +} + /** * Handle 'save' * @@ -215,6 +268,9 @@ function act_save($act){ //unlock it unlock($ID); + //delete draft + act_draftdel($act); + //show it session_write_close(); header("Location: ".wl($ID,'',true)); @@ -259,6 +315,7 @@ function act_auth($act){ */ function act_edit($act){ global $ID; + global $INFO; //check if locked by anyone - if not lock for my self $lockedby = checklock($ID); diff --git a/inc/common.php b/inc/common.php index ffb78f432..a2facee90 100644 --- a/inc/common.php +++ b/inc/common.php @@ -36,14 +36,17 @@ function pageinfo(){ $info['userinfo'] = $USERINFO; $info['perm'] = auth_quickaclcheck($ID); $info['subscribed'] = is_subscribed($ID,$_SERVER['REMOTE_USER']); + $info['client'] = $_SERVER['REMOTE_USER']; // if some outside auth were used only REMOTE_USER is set if(!$info['userinfo']['name']){ $info['userinfo']['name'] = $_SERVER['REMOTE_USER']; } + }else{ $info['perm'] = auth_aclcheck($ID,'',null); $info['subscribed'] = false; + $info['client'] = clientIP(true); } $info['namespace'] = getNS($ID); @@ -86,6 +89,17 @@ function pageinfo(){ $info['editor'] = $revinfo['ip']; } + // 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; + } + } + return $info; } diff --git a/inc/html.php b/inc/html.php index c0ce8527f..0cc52fbd1 100644 --- a/inc/html.php +++ b/inc/html.php @@ -98,7 +98,7 @@ function html_login(){ } /** - * shows the edit/source/show button dependent on current mode + * shows the edit/source/show/draft button dependent on current mode * * @author Andreas Gohr */ @@ -110,10 +110,14 @@ function html_editbutton(){ if($ACT == 'show' || $ACT == 'search'){ if($INFO['writable']){ - if($INFO['exists']){ - $r = html_btn('edit',$ID,'e',array('do' => 'edit','rev' => $REV),'post'); + if($INFO['draft']){ + $r = html_btn('draft',$ID,'e',array('do' => 'draft'),'post'); }else{ - $r = html_btn('create',$ID,'e',array('do' => 'edit','rev' => $REV),'post'); + if($INFO['exists']){ + $r = html_btn('edit',$ID,'e',array('do' => 'edit','rev' => $REV),'post'); + }else{ + $r = html_btn('create',$ID,'e',array('do' => 'edit','rev' => $REV),'post'); + } } }else{ $r = html_btn('source',$ID,'v',array('do' => 'edit','rev' => $REV),'post'); @@ -286,6 +290,36 @@ function html_show($txt=''){ } } +/** + * ask the user about how to handle an exisiting draft + * + * @author Andreas Gohr + */ +function html_draft(){ + global $INFO; + global $ID; + global $lang; + global $conf; + $draft = unserialize(io_readFile($INFO['draft'],false)); + $text = cleanText(con($draft['prefix'],$draft['text'],$draft['suffix'],true)); + + echo p_locale_xhtml('draft'); + ?> +
+ +
+ + +
+ + + + +
+
+
@@ -1012,8 +1047,8 @@ function html_edit($text=null,$include='edit'){ //FIXME: include needed? textChanged = ; -
+
@@ -1025,7 +1060,7 @@ function html_edit($text=null,$include='edit'){ //FIXME: include needed?
- +
diff --git a/inc/io.php b/inc/io.php index 1d458ace9..ae1a3611c 100644 --- a/inc/io.php +++ b/inc/io.php @@ -33,6 +33,9 @@ function io_sweepNS($id,$basedir='datadir'){ * * Uses gzip if extension is .gz * + * If you want to use the returned value in unserialize + * be sure to set $clean to false! + * * @author Andreas Gohr */ function io_readFile($file,$clean=true){ diff --git a/inc/lang/en/lang.php b/inc/lang/en/lang.php index 1a4308125..c1aa6bd6c 100644 --- a/inc/lang/en/lang.php +++ b/inc/lang/en/lang.php @@ -36,9 +36,12 @@ $lang['btn_backlink'] = "Backlinks"; $lang['btn_backtomedia'] = 'Back to Mediafile Selection'; $lang['btn_subscribe'] = 'Subscribe Changes'; $lang['btn_unsubscribe'] = 'Unsubscribe Changes'; -$lang['btn_profile'] = 'Update Profile'; -$lang['btn_reset'] = 'Reset'; -$lang['btn_resendpwd'] = 'Send new password'; +$lang['btn_profile'] = 'Update Profile'; +$lang['btn_reset'] = 'Reset'; +$lang['btn_resendpwd'] = 'Send new password'; +$lang['btn_draft'] = 'Edit draft'; +$lang['btn_recover'] = 'Recover draft'; +$lang['btn_draftdel'] = 'Delete draft'; $lang['loggedinas'] = 'Logged in as'; $lang['user'] = 'Username'; @@ -53,6 +56,7 @@ $lang['register'] = 'Register'; $lang['profile'] = 'User Profile'; $lang['badlogin'] = 'Sorry, username or password was wrong.'; $lang['minoredit'] = 'Minor Changes'; +$lang['draftdate'] = 'Draft autosaved on'; // full dformat date will be added $lang['regmissing'] = 'Sorry, you must fill in all fields.'; $lang['reguexists'] = 'Sorry, a user with this login already exists.'; diff --git a/inc/template.php b/inc/template.php index 091cd2e56..a74067f8b 100644 --- a/inc/template.php +++ b/inc/template.php @@ -53,8 +53,8 @@ function template($tpl){ * (defined by the global $ACT var) by calling the appropriate * outputfunction(s) from html.php * - * Everything that doesn't use the default template isn't - * handled by this function. ACL stuff is not done either. + * Everything that doesn't use the main template file isn't + * handled by this function. ACL stuff is not done here either. * * @author Andreas Gohr */ @@ -74,9 +74,15 @@ function tpl_content(){ html_edit($TEXT); html_show($TEXT); break; + case 'recover': + html_edit($TEXT); + break; case 'edit': html_edit(); break; + case 'draft': + html_draft(); + break; case 'wordblock': html_edit($TEXT,'wordblock'); break; @@ -203,7 +209,7 @@ function tpl_metaheaders($alt=true){ ptln('',$it); // load javascript - $js_edit = ($ACT=='edit' || $ACT=='preview') ? 1 : 0; + $js_edit = ($ACT=='edit' || $ACT=='preview' || $ACT=='recover') ? 1 : 0; $js_write = ($INFO['writable']) ? 1 : 0; if($js_edit && $js_write){ ptln('