Redirect.php

<?php

namespace Lia;

class Redirect extends \Lia\Compo {
    
    protected $redirectUrl;
    protected $withContent = false;
    protected $withMessage = false;
    protected $statusCode = 302;
    protected $message = null;


    public function onReady(){
        $lia = $this->lia;
    
        $lia->addApi('lia:goto.goto',[$this,'goto']);
        $lia->addApiMethod('lia:goto.goto', 'goto');
        $lia->addApi('lia:goto.setmessage',[$this,'gotoSetMessage']);
        $lia->addApiMethod('lia:goto.setmessage', 'gotoSetMessage');
        $lia->addApi('lia:goto.withmessage',[$this,'gotoWithMessage']);
        $lia->addApiMethod('lia:goto.withmessage', 'gotoWithMessage');
        $lia->addApi('lia:goto.withcontent',[$this,'gotoWithContent']);
        $lia->addApiMethod('lia:goto.withcontent', 'gotoWithContent');
        $lia->addApi('lia:goto.getmessage',[$this,'getGotoMessage']);
        $lia->addApiMethod('lia:goto.getmessage', 'getGotoMessage');

        $lia->addApi('lia:goto.setHeadersNow',[$this,'setHeadersNow']);
    }

    public function goto($url, $statusCode=302){
        $this->redirectUrl = $url;
        $this->statusCode = $statusCode;
        $this->withContent = false;
        $this->withMessage = false;
    }
    public function gotoSetMessage($message){
        $this->message = $message;
        $this->withMessage = true;
        $this->withContent = false;
    }
    
    public function gotoWithMessage($url, $message, $statusCode=302){
        $this->redirectUrl = $url;
        $this->withContent = false;
        $this->withMessage = true;
        $this->message = $message;
        $this->statusCode = $statusCode;
    }
    
    /**
     * Show the content of this request at the given url
     * Your target route must check for a goto message with getGotoMessage()
     */
    public function gotoWithContent($url, $statusCode=302){
        $this->redirectUrl = $url;
        $this->withContent = true;
        $this->statusCode = $statusCode;
        $this->withMessage = false;
    }
    
    /**
     * Get the message (if set) from the last goto() call
     *   
     * @return string|null
     */
    public function getGotoMessage() {
        $id = $_GET['message_id']??null;
        if ($id===null)return false;
        $cacheFile = $this->lia->getCacheFile('lia.Redirect.withMessage.'.$id);
        if (!is_file($cacheFile))return false;
        $content = file_get_contents($cacheFile);
        return $content;
    }

    public function setHeadersNow($route, $response){
        if ($this->redirectUrl=='')return;
        $response->useTheme = false;
        $response->sendContent = false;
        $id = uniqid().'-'.uniqid();
        $message = 
            $this->withMessage 
                ? $this->message 
                : ($this->withContent ? $response->content : false)
                ;
        
        $url = $this->redirectUrl;
        if ($message!==false){
            //cache the message for 20 seconds
            $this->lia->cacheFile('lia.Redirect.withMessage.'.$id, $message, 20);            

            $path = parse_url($url, PHP_URL_PATH);
            $query = parse_url($url, PHP_URL_QUERY);
            $qps = [];
            parse_str($query, $qps);
            $qps['message_id'] = $id;

            $url = $path.'?'.http_build_query($qps);
        } 
        $response->addHeader(["Location: {$url}", $this->statusCode ?? 302]);
    }
    
    /**
     * Set `Location: $gotoUrl` header to $response. 
     *
     */
    public function onEmitRouteResolved($route, $response){
        $this->setHeadersNow($route, $response);
    }
}