Not logged in. · Lost password · Register
Forum: General Help and Support Development RSS
act_redirect in Greebo?
My plugin used act_redirect() in Frusterick; function does not exist in Greebo.
Avatar
clh #1
Member since May 2016 · 94 posts
Group memberships: Members
Show profile · Link to this post
Subject: act_redirect in Greebo?
I'm updating a plugin I developed in Frusterick Manners to be compatible with Greebo. It makes several calls within its handle_ACTION_ACT_PREPROCESS_before() code to act_redirect(), which used to be in inc/action.php but isn't in Greebo.

I saw in the release notes that ACTION_ACT_PREPROCESS had undergone some changes that might affect plugins. I'm guessing this is one of those. The release notes don't lead to any details about the changes, and searching the forum turns up nothing recent, so I'm sort of stuck.

Could anyone point out developer documentation of the Greebo changes, or tell me how to replace act_redirect() in my code?

Thanks
This post was edited on 2019-01-05, 21:03 by clh.
Avatar
LarsDW223 #2
Member since Sep 2014 · 429 posts · Location: Paderborn
Group memberships: Members
Show profile · Link to this post
I think you have to overwrite the current event with the event redirect. E.g. see this commit https://github.com/dokufreaks/plugin-blogtng/commit/a4dfb2… in the blogtng plugin.
Avatar
clh #3
Member since May 2016 · 94 posts
Group memberships: Members
Show profile · Link to this post
LarsDW223, I think there's more to it than that. The code you referenced doesn't appear to establish a target to redirect to, unless I've missed it. Here is the complete function:

function handle_act_preprocess(Doku_Event $event, $param) {
        global $INFO, $ID;
        // optin
        if (isset($_REQUEST['btngo'])) {
            $this->commenthelper->optin($_REQUEST['btngo']);
        }
        // unsubscribe
        if (isset($_REQUEST['btngu'])) {
            $this->commenthelper->unsubscribe_by_key(md5($ID), $_REQUEST['btngu']);
        }
        global $BLOGTNG;
        $BLOGTNG = array();
        // prepare data for comment form
        $comment = array();
        $comment['source'] = $this->tools->getParam('comment/source');
        $comment['name']   = (($commentname = $this->tools->getParam('comment/name'))) ? $commentname : $INFO['userinfo']['name'];
        $comment['mail']   = (($commentmail = $this->tools->getParam('comment/mail'))) ? $commentmail : $INFO['userinfo']['mail'];
        $comment['web']    = (($commentweb = $this->tools->getParam('comment/web'))) ? $commentweb : '';
        $comment['text']   = isset($_REQUEST['wikitext']) ? cleanText($_REQUEST['wikitext']) : null;
        $comment['pid']    = isset($_REQUEST['pid'])      ? $_REQUEST['pid']      : null;
        $comment['page']   = isset($_REQUEST['id'])       ? $_REQUEST['id']       : null;
        $comment['subscribe'] = isset($_REQUEST['blogtng']['subscribe']) ? $_REQUEST['blogtng']['subscribe'] : null;
        $comment['ip'] = clientIP(true);
        //add "http(s)://" to website
        if (!preg_match('/^http/',$comment['web']) && $comment['web'] != '') {
            $comment['web'] = 'http://'.$comment['web'];
        }
        $BLOGTNG['comment'] = $comment;
        $action = act_clean($event->data);
        if($action == 'comment_submit' || $action == 'comment_preview') {
            if($action == 'comment_submit') {
                $BLOGTNG['comment_action'] = 'submit';
            }
            else if($action == 'comment_preview') {
                $BLOGTNG['comment_action'] = 'preview';
            }
            // check for empty fields
            $BLOGTNG['comment_submit_errors'] = array();
            foreach(array('name', 'mail', 'text') as $field) {
                if(empty($comment[$field])) {
                    $BLOGTNG['comment_submit_errors'][$field] = true;
                }
            }
            // check CAPTCHA if available (on submit only)
            $captchaok = true;
            if($BLOGTNG['comment_action'] == 'submit'){
                /** @var helper_plugin_captcha $helper */
                $helper = null;
                if(@is_dir(DOKU_PLUGIN.'captcha')) $helper = plugin_load('helper','captcha');
                if(!is_null($helper) && $helper->isEnabled()){
                    $captchaok = $helper->check();
                }
            }
            // return on errors
            if(!empty($BLOGTNG['comment_submit_errors']) || !$captchaok) {
                $event->data = 'show';
                $_SERVER['REQUEST_METHOD'] = 'get'; //hack to avoid redirect
                return false;
            }
Relevant code begins here

            if($BLOGTNG['comment_action'] == 'submit') {
                // save comment and redirect FIXME cid
                $this->commenthelper->save($comment);
                $event->data = 'redirect';
                return false;
            } elseif($BLOGTNG['comment_action'] == 'preview') {
                $event->data = 'show';
                $_SERVER['REQUEST_METHOD'] = 'get'; // hack to avoid redirect
                return false;
            }
        } else {
            return true;
        }
    }
}




So, this is my original Frusterick code. It causes navigation to a wikilink, displaying a message in the message area:

$msg = "You are now viewing the checked-out copy";
msg($msg, 1); // 1 means success (green background)
act_redirect(cleanID("drafts:$project:$canonical_id"), 'show');
return true;

Unrolling the call to act_redirect():

function act_redirect($id,$preact){
    global $PRE;
    global $TEXT;

      [.. omit irrelevant code for section edit]
    $opts = array(
            'id'       => $id,
            'preact'   => $preact
            );

    trigger_event('ACTION_SHOW_REDIRECT',$opts,'act_redirect_execute');
}

function act_redirect_execute($opts){
    $go = wl($opts['id'],'',true);
      [.. omit irrelevant code for section edit]
    send_redirect($go);
}

function send_redirect($url) {
    $url = stripctl($url); // defend against HTTP Response Splitting

    /* @var Input $INPUT */
    global $INPUT;

    //are there any undisplayed messages? keep them in session for display
    global $MSG;
    if(isset($MSG) && count($MSG) && !defined('NOSESSION')) {
        //reopen session, store data and close session again
        @session_start();
        $_SESSION[DOKU_COOKIE]['msg'] = $MSG;
    }

    // always close the session
    session_write_close();

      [.. omit code for running on IIS < 6]
    header('Location: '.$url);

    if(defined('DOKU_UNITTEST')) return; // no exits during unit tests
    exit;
}

So, in addition to overwriting the current event, how does one specify where to redirect to?
Avatar
LarsDW223 #4
Member since Sep 2014 · 429 posts · Location: Paderborn
Group memberships: Members
Show profile · Link to this post
In file {DOKUWIKI-INBSTALLATION-DIR}/inc/Action/Redirect.php you will find this code:

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('show');
    }

    /**
     * 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);
    }
}

I think you have to set 'id' in the event data to the page you want to redirect to. Optionally also 'fragment' can be set to specify an anchor/heading on the page to jump to.
Avatar
clh #5
Member since May 2016 · 94 posts
Group memberships: Members
Show profile · Link to this post
Here's what I did, that appears to work:

Frusterick:

act_redirect(cleanID("drafts:$project:$canonical_id"), 'show');
return false;

Greebo:

send_redirect(wl(cleanID("drafts:$project:$canonical_id"), '', true));
return false;

I wasn't able to figure out how to call the redirect() function in inc/Action/Redirect.php, but I found several examples plugins calling send_redirect() so I went with that.
Avatar
LarsDW223 #6
Member since Sep 2014 · 429 posts · Location: Paderborn
Group memberships: Members
Show profile · Link to this post
Ok, sorry I wasn't explicit enough. I only meant setting the event to 'redirect' and also change the event data for 'id' and 'fragment'.
The redirect() from the code will be called on changing the event to 'redirect'.

Anyway, it works now. Good.
Avatar
schplurtz (Moderator) #7
Member since Nov 2009 · 470 posts · Location: France, Finistère
Group memberships: Global Moderators, Members
Show profile · Link to this post
In reply to post #5
Quote by clh:
I wasn't able to figure out how to call the redirect() function in inc/Action/Redirect.php

I think you don't call it directly. It's a callback function that's called by something that handles the ACTION_SHOW_REDIRECT event which is somehow triggered when you call throw new ActionAbort('redirect');, which seems to be the new way of switching from current action to viewing the current page. If you look at DW commit 272271fce, you'll see line 94/91 of inc/Action/Subscribe.php that act_redirect() is replaced by throw new ActionAbort('redirect');

As a non PHP dev, I find this overcomplicated.

Also, send_redirect() already exists in Frusterick. Your plugin should work in both version
Close Smaller – Larger + Reply to this post:
Verification code: VeriCode Please enter the word from the image into the text field below. (Type the letters only, lower case is okay.)
Smileys: :-) ;-) :-D :-p :blush: :cool: :rolleyes: :huh: :-/ <_< :-( :'( :#: :scared: 8-( :nuts: :-O
Special characters:
Go to forum
Imprint
This board is powered by the Unclassified NewsBoard software, 20150713-dev, © 2003-2015 by Yves Goergen
Current time: 2019-09-23, 15:54:41 (UTC +02:00)