themosis / framework

The Themosis framework core.
https://framework.themosis.com/
GNU General Public License v2.0
671 stars 121 forks source link

Implement session full support on administration pages #621

Open jlambe opened 5 years ago

jlambe commented 5 years ago

Currently the session is not fully working on the administration of WordPress.

The session driver is well loaded but no data can be stored or "fetched" from an administration page. If a session value defined on the front-end is still available to the session, it can still be returned from an administration page.

The main issue is that the session driver does not seem to store session data from the administration only.

maximusblade commented 5 years ago

I'm not sure if this is the same as the issue I'm having.

For some reason I am unable to get a session to persist across requests? I have middleware that sets "locale" But when I try to retrieve this value in controller....I get a blank value.

<?php
namespace App\Http\Middleware;
use Closure;

class CheckUserLocale
{
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @return mixed
*/
public function handle($request, Closure $next)
{
if ($request->has('locale')){
$locale = $request->input('locale', env('USER_REGION'));
session(['locale' => $locale]);
}
return $next($request);
}
}

Controller::

<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App;
class LocalizationController extends Controller
{
    public function what_is_user_locale(){
        $value = session('locale');
        dd($value); // null
    }

} 

Thanks in advance.

jlambe commented 5 years ago

@maximusblade Hmm not sure regarding your issue but I think it seems an issue with the order of the middleware stack. If your middleware is called before the session manager has been initialized (middleware), it is expected. You might want to try to sort your middlewares inside the App\Http\Kernel.php class:

The issue here is regarding the WordPress administration screens only.

maximusblade commented 5 years ago

@jlambe Hey thanks for the reply I have tried middleware sorting. I made sure that sessionStart fires off before any of my middleware. I'll open up a new issue since this may not be related.

pvdptje commented 5 years ago

@jlambe I've added a really nasty hack to get sessions working on admin pages. I think the problem is in the fact that the script gets killed when the admin page is loaded. In wp-admin/admin.php on line 292:


    include( ABSPATH . 'wp-admin/admin-footer.php' );

    exit();

I know, at least in Laravel, sessions do not persist when the script is killed with either exit or dd. When i change the code to this:

include( ABSPATH . 'wp-admin/admin-footer.php' );

    register_shutdown_function(function(){
        app()['session']->save();
    });

    exit();

All sessions are saved.

The only thing is, i dont know how to properly implement this, but for now i can do my thing. Maybe this helps you come up with a good solution!

jlambe commented 5 years ago

@pvdptje this is at least a very useful information to explore and for now the best thing to track, thanks!

pvdptje commented 5 years ago

I've found a cleaner solution, which doesn't require editing Wordpress core files. Make a new hook:

namespace App\Hooks;

use Themosis\Hook\Hookable;
use Themosis\Support\Facades\Action;

class PersistSessions extends Hookable
{
    public function register()
    {
        Action::add('shutdown', function(){
            app()['session']->save();
        });
    }
}

Register this in config/app.php and it works as well!

jlambe commented 5 years ago

@pvdptje Sweet! I'll definitely test this trick.

besrabasant commented 5 years ago

@pvdptje This solution works. Though, I have been facing similar issues with wp_cache_* functions.

jlambe commented 5 years ago

@pvdptje I've tested this and it does work better. One thing I haven't yet eluded is when using the session()->flash() method.

For unknown reasons, the session data is not persisted on the next request when using the flash method. Did you have the same issue in your tests ?

toscani commented 5 years ago

I just tested flash() and it didn't work. I don't really have time to dig into this, but i took a quick look and added some hacks to the session core files, and got it to work.

In illuminate\session\Middleware\Startsession on line 65 the save method is called on the driver. Comment this line out.

Make sure you use the file session handler, and in Illuminate\Session\FileSessionHandler

Change the write method to this:

static $written = false;
    /**
     * {@inheritdoc}
     */
    public function write($sessionId, $data)
    {
        if(!static::$written){
            $this->files->put($this->path.'/'.$sessionId, $data, true);
            static::$written = true;
        }

        return true;
    }

I've added the following code to a controller:

    {
        if(!session()->has('test')){
            echo 'No flash data yet, setting it';
            session()->flash('test', '123');
        } else {
            print_r(session()->all());
        }

        return view('test');
    }

Sets the flash data the first request, and displays it the second. The write method on the handler is called multiple times, and the last time it just clears all flash data. No idea why (yet).