Skip to content
This repository has been archived by the owner on Jan 29, 2020. It is now read-only.

Commit

Permalink
Merging develop to master in preparation for 1.2.0 release
Browse files Browse the repository at this point in the history
  • Loading branch information
weierophinney committed Oct 30, 2018
2 parents e966e1f + 30b7d3e commit de67a64
Show file tree
Hide file tree
Showing 10 changed files with 356 additions and 12 deletions.
15 changes: 12 additions & 3 deletions CHANGELOG.md
Expand Up @@ -2,15 +2,24 @@

All notable changes to this project will be documented in this file, in reverse chronological order by release.

## 1.1.1 - TBD
## 1.2.0 - 2018-10-30

### Added

- Nothing.
- [#28](https://github.com/zendframework/zend-expressive-session/pull/28) adds a new interface, `SessionCookiePersistenceInterface`, defining:
- the constant `SESSION_LIFETIME_KEY`
- the method `persistSessionFor(int $duration) : void`, for developers to hint
to the persistence engine how long a session should last
- the method `getSessionLifetime() : int`, for persistence engines to
determine if a specific session duration was requested

### Changed

- Nothing.
- [#28](https://github.com/zendframework/zend-expressive-session/pull/28) updates both `Session` and `LazySession` to implement the new
`SessionCookiePersistenceInterface. If a `SessionCookiePersistenceInterface::SESSION_LIFETIME_KEY`
is present in the initial session data provided to a `Session` instance, this
value will be used to indicate the requested session duration; otherwise, zero
is used, indicating the session should end when the browser is closed.

### Deprecated

Expand Down
4 changes: 2 additions & 2 deletions composer.json
Expand Up @@ -51,8 +51,8 @@
},
"extra": {
"branch-alias": {
"dev-master": "1.1.x-dev",
"dev-develop": "1.2.x-dev"
"dev-master": "1.2.x-dev",
"dev-develop": "1.3.x-dev"
},
"zf": {
"config-provider": "Zend\\Expressive\\Session\\ConfigProvider"
Expand Down
4 changes: 2 additions & 2 deletions composer.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

30 changes: 30 additions & 0 deletions docs/book/persistence.md
Expand Up @@ -83,3 +83,33 @@ Considering that persistence implementations also _create_ the session instance,
we recommend that implementations only create instances that implement the
`SessionIdentifierAwareInterface` going forward in order to make themselves
async compatible.

## Persistent sessions

- Since 1.2.0.

If your persistence implementation supports persistent sessions — for
example, by setting an `Expires` or `Max-Age` cookie directive — then you
can opt to globally set a default session duration, or allow developers to hint
a desired session duration via the session container using
`SessionContainerPersistenceInterface::persistSessionFor()`.

Implementations SHOULD honor the value of `SessionContainerPersistenceInterface::getSessionLifetime()`
when persisting the session data. This could mean either or both of the
following:

- Ensuring that the session data will not be purged until after the specified
TTL value.
- Setting an `Expires` or `Max-Age` cookie directive.

In each case, the persistence engine should query the `Session` instance for a
TTL value:

```php
$ttl = $session instanceof SessionContainerPersistenceInterface
? $session->getSessionLifetime()
: $defaultLifetime; // likely 0, to indicate automatic expiry
```

`getSessionLifetime()` returns an `integer` value indicating the number of
seconds the session should persist.
93 changes: 90 additions & 3 deletions docs/book/session.md
Expand Up @@ -79,7 +79,7 @@ interface SessionInterface
The default implementation, and the one you'll most likely interact with, is
`Zend\Expressive\Session\Session`.

Additionally, since version 1.1.0, we provide `Zend\Expressive\Session\SessionIdentifierAwareInterface`:
Since version 1.1.0, we provide `Zend\Expressive\Session\SessionIdentifierAwareInterface`:

```php
namespace Zend\Expressive\Session;
Expand All @@ -103,9 +103,78 @@ interface SessionIdentifierAwareInterface
}
```

Since version 1.2.0, we provide `Zend\Expressive\Session\SessionCookiePersistenceInterface`:

```php
namespace Zend\Expressive\Session;

/**
* Allow marking session cookies as persistent.
*
* It can be useful to mark a session as persistent: e.g., for a "Remember Me"
* feature when logging a user into your system. PHP provides this capability
* via ext-session with the $lifetime argument to session_set_cookie_params()
* as well as by the session.cookie_lifetime INI setting. The latter will set
* the value for all session cookies sent (or until the value is changed via
* an ini_set() call), while the former will only affect cookies created during
* the current script lifetime.
*
* Persistence engines may, of course, allow setting a global lifetime. This
* interface allows developers to set the lifetime programmatically. Persistence
* implementations are encouraged to use the value to set the cookie lifetime
* when creating and returning a cookie. Additionally, to ensure the cookie
* lifetime originally requested is honored when a session is regenerated, we
* recommend persistence engines to store the TTL in the session data itself,
* so that it can be re-sent in such scenarios.
*/
interface SessionCookiePersistenceInterface
{
const SESSION_LIFETIME_KEY = '__SESSION_TTL__';

/**
* Define how long the session cookie should live.
*
* Use this value to detail to the session persistence engine how long the
* session cookie should live.
*
* This value could be passed as the $lifetime value of
* session_set_cookie_params(), or used to create an Expires or Max-Age
* parameter for a session cookie.
*
* Since cookie lifetime is communicated by the server to the client, and
* not vice versa, the value should likely be persisted in the session
* itself, to ensure that session regeneration uses the same value. We
* recommend using the SESSION_LIFETIME_KEY value to communicate this.
*
* @param int $duration Number of seconds the cookie should persist for.
*/
public function persistSessionFor(int $duration) : void;

/**
* Determine how long the session cookie should live.
*
* Generally, this will return the value provided to persistFor().
*
* If that method has not been called, the value can return one of the
* following:
*
* - 0 or a negative value, to indicate the cookie should be treated as a
* session cookie, and expire when the window is closed. This should be
* the default behavior.
* - If persistFor() was provided during session creation or anytime later,
* the persistence engine should pull the TTL value from the session itself
* and return it here. Typically, this value should be communicated via
* the SESSION_LIFETIME_KEY value of the session.
*/
public function getSessionLifetime() : int;
}
```

`Zend\Expressive\Session\Session` and `Zend\Expressive\Session\LazySession` both
implement this interface. `Session` accepts an optional identifier to its
constructor.
implement each of the interfaces listed above. `Session` accepts an optional
identifier to its constructor, and will use the value of the
`SessionCookiePersistenceInterface::SESSION_LIFETIME_KEY` in the provided data
to seed the session cookie lifetime, if present.

## Usage

Expand Down Expand Up @@ -146,6 +215,24 @@ If none of the data is relevant, `clear()` the session:
$session->clear();
```

### Persistent Sessions

- Since 1.2.0

You can hint to the session persistence engine how long the session should
persist:

```php
$session->persistSessionFor(60 * 60 * 24 * 7); // persist for 7 days
```

To make the session expire when the browser session is terminated (default
behavior), use zero or a negative integer:

```php
$session->persistSessionFor(0); // expire data after session is over
```

## Lazy Sessions

This package provides another implementation of `SessionInterface` via
Expand Down
31 changes: 30 additions & 1 deletion src/LazySession.php
Expand Up @@ -19,7 +19,10 @@
* method only on access to any of the various session data methods; otherwise,
* the session will not be accessed, and, in most cases, started.
*/
final class LazySession implements SessionInterface, SessionIdentifierAwareInterface
final class LazySession implements
SessionCookiePersistenceInterface,
SessionIdentifierAwareInterface,
SessionInterface
{
/**
* @var SessionPersistenceInterface
Expand Down Expand Up @@ -113,6 +116,32 @@ public function getId() : string
: '';
}

/**
* {@inheritDoc}
*
* @since 1.2.0
*/
public function persistSessionFor(int $duration) : void
{
$proxiedSession = $this->getProxiedSession();
if ($proxiedSession instanceof SessionCookiePersistenceInterface) {
$proxiedSession->persistSessionFor($duration);
}
}

/**
* {@inheritDoc}
*
* @since 1.2.0
*/
public function getSessionLifetime() : int
{
$proxiedSession = $this->getProxiedSession();
return $proxiedSession instanceof SessionCookiePersistenceInterface
? $proxiedSession->getSessionLifetime()
: 0;
}

private function getProxiedSession() : SessionInterface
{
if ($this->proxiedSession) {
Expand Down
37 changes: 36 additions & 1 deletion src/Session.php
Expand Up @@ -9,7 +9,10 @@

namespace Zend\Expressive\Session;

class Session implements SessionInterface, SessionIdentifierAwareInterface
class Session implements
SessionCookiePersistenceInterface,
SessionIdentifierAwareInterface,
SessionInterface
{
/**
* Current data within the session.
Expand Down Expand Up @@ -43,10 +46,21 @@ class Session implements SessionInterface, SessionIdentifierAwareInterface
*/
private $originalData;

/**
* Lifetime of the session cookie.
*
* @var int
*/
private $sessionLifetime = 0;

public function __construct(array $data, string $id = '')
{
$this->data = $this->originalData = $data;
$this->id = $id;

if (isset($data[SessionCookiePersistenceInterface::SESSION_LIFETIME_KEY])) {
$this->sessionLifetime = $data[SessionCookiePersistenceInterface::SESSION_LIFETIME_KEY];
}
}

/**
Expand Down Expand Up @@ -133,4 +147,25 @@ public function getId() : string
{
return $this->id;
}

/**
* {@inheritDoc}
*
* @since 1.2.0
*/
public function persistSessionFor(int $duration) : void
{
$this->sessionLifetime = $duration;
$this->set(SessionCookiePersistenceInterface::SESSION_LIFETIME_KEY, $duration);
}

/**
* {@inheritDoc}
*
* @since 1.2.0
*/
public function getSessionLifetime() : int
{
return $this->sessionLifetime;
}
}
69 changes: 69 additions & 0 deletions src/SessionCookiePersistenceInterface.php
@@ -0,0 +1,69 @@
<?php
/**
* @see https://github.com/zendframework/zend-expressive-session for the canonical source repository
* @copyright Copyright (c) 2018 Zend Technologies USA Inc. (http://www.zend.com)
* @license https://github.com/zendframework/zend-expressive-session/blob/master/LICENSE.md New BSD License
*/

namespace Zend\Expressive\Session;

/**
* Allow marking session cookies as persistent.
*
* It can be useful to mark a session as persistent: e.g., for a "Remember Me"
* feature when logging a user into your system. PHP provides this capability
* via ext-session with the $lifetime argument to session_set_cookie_params()
* as well as by the session.cookie_lifetime INI setting. The latter will set
* the value for all session cookies sent (or until the value is changed via
* an ini_set() call), while the former will only affect cookies created during
* the current script lifetime.
*
* Persistence engines may, of course, allow setting a global lifetime. This
* interface allows developers to set the lifetime programmatically. Persistence
* implementations are encouraged to use the value to set the cookie lifetime
* when creating and returning a cookie. Additionally, to ensure the cookie
* lifetime originally requested is honored when a session is regenerated, we
* recommend persistence engines to store the TTL in the session data itself,
* so that it can be re-sent in such scenarios.
*/
interface SessionCookiePersistenceInterface
{
const SESSION_LIFETIME_KEY = '__SESSION_TTL__';

/**
* Define how long the session cookie should live.
*
* Use this value to detail to the session persistence engine how long the
* session cookie should live.
*
* This value could be passed as the $lifetime value of
* session_set_cookie_params(), or used to create an Expires or Max-Age
* parameter for a session cookie.
*
* Since cookie lifetime is communicated by the server to the client, and
* not vice versa, the value should likely be persisted in the session
* itself, to ensure that session regeneration uses the same value. We
* recommend using the SESSION_LIFETIME_KEY value to communicate this.
*
* @param int $duration Number of seconds the cookie should persist for.
*/
public function persistSessionFor(int $duration) : void;

/**
* Determine how long the session cookie should live.
*
* Generally, this will return the value provided to persistFor().
*
* If that method has not been called, the value can return one of the
* following:
*
* - 0 or a negative value, to indicate the cookie should be treated as a
* session cookie, and expire when the window is closed. This should be
* the default behavior.
* - If persistFor() was provided during session creation or anytime later,
* the persistence engine should pull the TTL value from the session itself
* and return it here. Typically, this value should be communicated via
* the SESSION_LIFETIME_KEY value of the session.
*/
public function getSessionLifetime() : int;
}

0 comments on commit de67a64

Please sign in to comment.