Skip to content

Commit

Permalink
Improved Session initialization (#1879)
Browse files Browse the repository at this point in the history
  • Loading branch information
mahagr authored and rhukster committed Feb 21, 2018
1 parent 7cfc6fb commit 42d8836
Show file tree
Hide file tree
Showing 6 changed files with 179 additions and 114 deletions.
3 changes: 2 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@
* Added `$grav['uri]->getCurrentRoute()` method to get `Grav\Framework\Route\Route` instance for the current URL
* Added ability to have `php` version dependencies in GPM assets
1. [](#improved)
* Vendor library updated to latest
* Vendor library updated to latest
* Improved `Session` initialization
1. [](#bugfix)
* Fixed issue with remote PHP version determination for Grav updates

Expand Down
3 changes: 1 addition & 2 deletions system/src/Grav/Common/Grav.php
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,7 @@ class Grav extends Container
'uri' => 'Grav\Common\Uri',
'events' => 'RocketTheme\Toolbox\Event\EventDispatcher',
'cache' => 'Grav\Common\Cache',
'session' => 'Grav\Common\Session',
'Grav\Common\Service\MessagesServiceProvider',
'Grav\Common\Service\SessionServiceProvider',
'plugins' => 'Grav\Common\Plugins',
'themes' => 'Grav\Common\Themes',
'twig' => 'Grav\Common\Twig\Twig',
Expand Down
2 changes: 1 addition & 1 deletion system/src/Grav/Common/Processors/InitializeProcessor.php
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ public function process()
}

// FIXME: Initialize session should happen later after plugins have been loaded. This is a workaround to fix session issues in AWS.
if ($this->container['config']->get('system.session.initialize', 1)) {
if ($this->container['config']->get('system.session.initialize', 1) && isset($this->container['session'])) {
$this->container['session']->init();
}

Expand Down
41 changes: 0 additions & 41 deletions system/src/Grav/Common/Service/MessagesServiceProvider.php

This file was deleted.

105 changes: 105 additions & 0 deletions system/src/Grav/Common/Service/SessionServiceProvider.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
<?php
/**
* @package Grav.Common.Service
*
* @copyright Copyright (C) 2015 - 2018 Trilby Media, LLC. All rights reserved.
* @license MIT License; see LICENSE file for details.
*/

namespace Grav\Common\Service;

use Grav\Common\Config\Config;
use Grav\Common\Debugger;
use Grav\Common\Inflector;
use Grav\Common\Session;
use Grav\Common\Uri;
use Pimple\Container;
use Pimple\ServiceProviderInterface;
use RocketTheme\Toolbox\Session\Message;

class SessionServiceProvider implements ServiceProviderInterface
{
public function register(Container $container)
{
// Define session service.
$container['session'] = function ($c) {
/** @var Config $config */
$config = $c['config'];

/** @var Uri $uri */
$uri = $c['uri'];

// Get session parameters.
$session_timeout = (int)$config->get('system.session.timeout', 1800);
$session_path = $config->get('system.session.path');
if (null === $session_path) {
$session_path = '/' . ltrim(Uri::filterPath($uri->rootUrl(false)), '/');
}
$domain = $uri->host();
if ($domain === 'localhost') {
$domain = '';
}

// Get session options.
$secure = (bool)$config->get('system.session.secure', false);
$httponly = (bool)$config->get('system.session.httponly', true);
$enabled = (bool)$config->get('system.session.enabled', false);

// Activate admin if we're inside the admin path.
$is_admin = false;
if ($config->get('plugins.admin.enabled')) {
$base = '/' . trim($config->get('plugins.admin.route'), '/');

// Uri::route() is not processed yet, let's quickly get what we need.
$current_route = str_replace(Uri::filterPath($uri->rootUrl(false)), '', parse_url($uri->url(true), PHP_URL_PATH));

// Check no language, simple language prefix (en) and region specific language prefix (en-US).
$pos = strpos($current_route, $base);
if ($pos === 0 || $pos === 3 || $pos === 6) {
$session_timeout = $config->get('plugins.admin.session.timeout', 1800);
$enabled = $is_admin = true;
}
}

// Fix for HUGE session timeouts.
if ($session_timeout > 99999999999) {
$session_timeout = 9999999999;
}

$inflector = new Inflector();
$session_name = $inflector->hyphenize($config->get('system.session.name', 'grav_site')) . '-' . substr(md5(GRAV_ROOT), 0, 7);
if ($is_admin && $config->get('system.session.split', true)) {
$session_name .= '-admin';
}

// Define session service.
$session = new Session($session_timeout, $session_path, $domain);
$session->setName($session_name);
$session->setSecure($secure);
$session->setHttpOnly($httponly);
$session->setAutoStart($enabled);

return $session;
};

// Define session message service.
$container['messages'] = function ($c) {
if (!isset($c['session']) || !$c['session']->started()) {
/** @var Debugger $debugger */
$debugger = $c['debugger'];
$debugger->addMessage('Inactive session: session messages may disappear', 'warming');

return new Message;
}

/** @var Session $session */
$session = $c['session'];

if (!isset($session->messages)) {
$session->messages = new Message;
}

return $session->messages;
};
}
}
139 changes: 70 additions & 69 deletions system/src/Grav/Common/Session.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,113 +12,114 @@

class Session extends BaseSession
{
protected $grav;
protected $session;
/** @var bool */
protected $autoStart = false;

/**
* Session constructor.
* Initialize session.
*
* @param Grav $grav
* Code in this function has been moved into SessionServiceProvider class.
*/
public function __construct(Grav $grav)
public function init()
{
$this->grav = $grav;
if ($this->autoStart) {
$this->start();

$this->autoStart = false;
}
}

/**
* Session init
* @param bool $auto
* @return $this
*/
public function init()
public function setAutoStart($auto)
{
/** @var Uri $uri */
$uri = $this->grav['uri'];
$config = $this->grav['config'];
$this->autoStart = (bool)$auto;

$is_admin = false;
$base_url = $uri->rootUrl(false);
return $this;
}

$session_timeout = $config->get('system.session.timeout', 1800);
$session_path = $config->get('system.session.path');
if (!$session_path) {
$session_path = '/' . ltrim(Uri::filterPath($base_url), '/');
}
/**
* @param bool $secure
* @return $this
*/
public function setSecure($secure)
{
ini_set('session.cookie_secure', (bool)$secure);

// Activate admin if we're inside the admin path.
if ($config->get('plugins.admin.enabled')) {
$route = $config->get('plugins.admin.route');
// Uri::route() is not processed yet, let's quickly get what we need
$current_route = str_replace(Uri::filterPath($base_url), '', parse_url($uri->url(true), PHP_URL_PATH));
$base = '/' . trim($route, '/');

if (substr($current_route, 0, strlen($base)) == $base || //handle no language specified
substr($current_route, 3, strlen($base)) == $base || //handle language (en)
substr($current_route, 6, strlen($base)) == $base) { //handle region specific language prefix (en-US)
$session_timeout = $config->get('plugins.admin.session.timeout', 1800);
$is_admin = true;
}
}
return $this;
}

if ($config->get('system.session.enabled') || $is_admin) {
$domain = $uri->host();
if ($domain === 'localhost') {
$domain = '';
}

// Fix for HUGE session timeouts
if ($session_timeout > 99999999999) {
$session_timeout = 9999999999;
}

// Define session service.
parent::__construct($session_timeout, $session_path, $domain);

$secure = $config->get('system.session.secure', false);
$httponly = $config->get('system.session.httponly', true);

$unique_identifier = GRAV_ROOT;
$inflector = new Inflector();
$session_name = $inflector->hyphenize($config->get('system.session.name', 'grav_site')) . '-' . substr(md5($unique_identifier), 0, 7);
$split_session = $config->get('system.session.split', true);
if ($is_admin && $split_session) {
$session_name .= '-admin';
}
$this->setName($session_name);
ini_set('session.cookie_secure', $secure);
ini_set('session.cookie_httponly', $httponly);
$this->start();
setcookie(session_name(), session_id(), $session_timeout ? time() + $session_timeout : 0, $session_path, $domain, $secure, $httponly);
}
/**
* @param bool $httponly
* @return $this
*/
public function setHttpOnly($httponly)
{
ini_set('session.cookie_httponly', (bool)$httponly);

return $this;
}

// Store something in session temporarily
/**
* Store something in session temporarily.
*
* @param string $name
* @param mixed $object
* @return $this
*/
public function setFlashObject($name, $object)
{
$this->$name = serialize($object);
$this->{$name} = serialize($object);

return $this;
}

// Return object and remove it from session
/**
* Return object and remove it from session.
*
* @param string $name
* @return mixed
*/
public function getFlashObject($name)
{
$object = unserialize($this->$name);
$object = unserialize($this->{$name});

$this->$name = null;
$this->{$name} = null;

return $object;
}

// Store something in cookie temporarily
/**
* Store something in cookie temporarily.
*
* @param string $name
* @param mixed $object
* @param int $time
* @return $this
*/
public function setFlashCookieObject($name, $object, $time = 60)
{
setcookie($name, json_encode($object), time() + $time, '/');

return $this;
}

// Return object and remove it from the cookie
/**
* Return object and remove it from the cookie.
*
* @param string $name
* @return mixed|null
*/
public function getFlashCookieObject($name)
{
if (isset($_COOKIE[$name])) {
$object = json_decode($_COOKIE[$name]);
setcookie($name, '', time() - 3600, '/');
return $object;
}

return null;
}
}

0 comments on commit 42d8836

Please sign in to comment.