From 58528803ad1f586696a6719f4ed566b78eb7b1d9 Mon Sep 17 00:00:00 2001 From: Andreas Gohr <andi@splitbrain.org> Date: Thu, 18 May 2017 12:58:50 +0200 Subject: [PATCH] introduce a redirect action Action can now abort to 'redirect' to explicitly trigger a redirect back to showing the current page. Automatic triggering for post->show is now only done when a 'show' action was not explicitly requested. --- inc/Action/Cancel.php | 2 +- inc/Action/Draftdel.php | 2 +- inc/Action/Exception/ActionException.php | 16 +++++- inc/Action/Redirect.php | 64 ++++++++++++++++++++++++ inc/Action/Revert.php | 5 +- inc/Action/Save.php | 2 +- inc/ActionRouter.php | 11 +--- inc/actions.php | 46 ----------------- 8 files changed, 83 insertions(+), 65 deletions(-) create mode 100644 inc/Action/Redirect.php diff --git a/inc/Action/Cancel.php b/inc/Action/Cancel.php index 3665f20c0..c72644607 100644 --- a/inc/Action/Cancel.php +++ b/inc/Action/Cancel.php @@ -14,7 +14,7 @@ use dokuwiki\Action\Exception\ActionAbort; class Cancel extends AbstractAliasAction { public function preProcess() { - throw new ActionAbort(); + throw new ActionAbort('draftdel'); } } diff --git a/inc/Action/Draftdel.php b/inc/Action/Draftdel.php index 092369564..d7707b30d 100644 --- a/inc/Action/Draftdel.php +++ b/inc/Action/Draftdel.php @@ -20,7 +20,7 @@ class Draftdel extends AbstractAction { public function preProcess() { act_draftdel('fixme'); // FIXME replace this utility function - throw new ActionAbort(); + throw new ActionAbort('redirect'); } } diff --git a/inc/Action/Exception/ActionException.php b/inc/Action/Exception/ActionException.php index 386364c59..381584c15 100644 --- a/inc/Action/Exception/ActionException.php +++ b/inc/Action/Exception/ActionException.php @@ -24,11 +24,23 @@ class ActionException extends \Exception { /** * ActionException constructor. * - * @param string $newaction the action that should be used next + * When no new action is given 'show' is assumed. For requests that originated in a POST, + * a 'redirect' is used which will cause a redirect to the 'show' action. + * + * @param string|null $newaction the action that should be used next * @param string $message optional message, will not be shown except for some dub classes */ - public function __construct($newaction = 'show', $message = '') { + public function __construct($newaction = null, $message = '') { + global $INPUT; parent::__construct($message); + if(is_null($newaction)) { + if(strtolower($INPUT->server->str('REQUEST_METHOD')) == 'post') { + $newaction = 'redirect'; + } else { + $newaction = 'show'; + } + } + $this->newaction = $newaction; } diff --git a/inc/Action/Redirect.php b/inc/Action/Redirect.php new file mode 100644 index 000000000..0e989d1ff --- /dev/null +++ b/inc/Action/Redirect.php @@ -0,0 +1,64 @@ +<?php + +namespace dokuwiki\Action; + +use dokuwiki\Action\Exception\ActionAbort; + +/** + * Class Redirect + * + * Used to redirect to the current page with the last edited section as a target if found + * + * @package dokuwiki\Action + */ +class Redirect extends AbstractAliasAction { + + /** + * Redirect to the show action, trying to jump to the previously edited section + * + * @triggers ACTION_SHOW_REDIRECT + * @throws ActionAbort + */ + public function preProcess() { + global $PRE; + global $TEXT; + global $INPUT; + global $ID; + global $ACT; + + $opts = array( + 'id' => $ID, + 'preact' => $ACT + ); + //get section name when coming from section edit + if($INPUT->has('hid')) { + // Use explicitly transmitted header id + $opts['fragment'] = $INPUT->str('hid'); + } else if($PRE && preg_match('/^\s*==+([^=\n]+)/', $TEXT, $match)) { + // Fallback to old mechanism + $check = false; //Byref + $opts['fragment'] = sectionID($match[0], $check); + } + + // execute the redirect + trigger_event('ACTION_SHOW_REDIRECT', $opts, array($this, 'redirect')); + + // should never be reached + throw new ActionAbort(); + } + + /** + * Execute the redirect + * + * Default action for ACTION_SHOW_REDIRECT + * + * @param array $opts id and fragment for the redirect and the preact + */ + public function redirect($opts) { + $go = wl($opts['id'], '', true); + if(isset($opts['fragment'])) $go .= '#' . $opts['fragment']; + + //show it + send_redirect($go); + } +} diff --git a/inc/Action/Revert.php b/inc/Action/Revert.php index 559121cce..4fd9d622f 100644 --- a/inc/Action/Revert.php +++ b/inc/Action/Revert.php @@ -37,7 +37,6 @@ class Revert extends AbstractAction { global $ID; global $REV; global $lang; - global $INPUT; // when no revision is given, delete current one // FIXME this feature is not exposed in the GUI currently @@ -63,10 +62,8 @@ class Revert extends AbstractAction { //session_write_close(); // FIXME sessions should be close somewhere higher up, maybe ActionRouter // when done, show current page - $INPUT->server->set('REQUEST_METHOD', 'post'); //should force a redirect // FIXME should we have a RedirectException? $REV = ''; - - throw new ActionAbort(); + throw new ActionAbort('redirect'); } } diff --git a/inc/Action/Save.php b/inc/Action/Save.php index dd6da567b..419108e1a 100644 --- a/inc/Action/Save.php +++ b/inc/Action/Save.php @@ -58,7 +58,7 @@ class Save extends AbstractAction { //session_write_close(); // FIXME close session higher up // when done, show page - throw new ActionAbort(); + throw new ActionAbort('redirect'); } } diff --git a/inc/ActionRouter.php b/inc/ActionRouter.php index 1e8f65bab..cb2df70ad 100644 --- a/inc/ActionRouter.php +++ b/inc/ActionRouter.php @@ -120,17 +120,13 @@ class ActionRouter { /** * Transitions from one action to another * - * Basically just calls setupAction() again but does some checks before. Also triggers - * redirects for POST to show transitions + * Basically just calls setupAction() again but does some checks before. * * @param string $from current action name * @param string $to new action name * @param null|ActionException $e any previous exception that caused the transition */ protected function transitionAction($from, $to, $e = null) { - global $INPUT; - global $ID; - $this->transitions++; // no infinite recursion @@ -143,11 +139,6 @@ class ActionRouter { $this->handleFatalException(new FatalException('Maximum action transitions reached', 500, $e)); } - // POST transitions to show should be a redirect - if($to == 'show' && strtolower($INPUT->server->str('REQUEST_METHOD')) == 'post') { - act_redirect($ID, $from); // FIXME we may want to move this function to the class - } - // do the recursion $this->setupAction($to); } diff --git a/inc/actions.php b/inc/actions.php index 6aa29f3bf..a384d327d 100644 --- a/inc/actions.php +++ b/inc/actions.php @@ -75,49 +75,3 @@ function act_draftdel($act){ $INFO['draft'] = null; return 'show'; } - -/** - * Do a redirect after receiving post data - * - * Tries to add the section id as hash mark after section editing - * - * @param string $id page id - * @param string $preact action command before redirect - */ -function act_redirect($id,$preact){ - global $PRE; - global $TEXT; - global $INPUT; - - $opts = array( - 'id' => $id, - 'preact' => $preact - ); - //get section name when coming from section edit - if ($INPUT->has('hid')) { - // Use explicitly transmitted header id - $opts['fragment'] = $INPUT->str('hid'); - } else if($PRE && preg_match('/^\s*==+([^=\n]+)/',$TEXT,$match)){ - // Fallback to old mechanism - $check = false; //Byref - $opts['fragment'] = sectionID($match[0], $check); - } - - trigger_event('ACTION_SHOW_REDIRECT',$opts,'act_redirect_execute'); -} - -/** - * Execute the redirect - * - * @param array $opts id and fragment for the redirect and the preact - */ -function act_redirect_execute($opts){ - $go = wl($opts['id'],'',true); - if(isset($opts['fragment'])) $go .= '#'.$opts['fragment']; - - //show it - send_redirect($go); -} - - -//Setup VIM: ex: et ts=2 : -- GitLab