* @link https://getkirby.com * @copyright Bastian Allgeier * @license https://opensource.org/licenses/MIT */ class AutoSession { protected $sessions; protected $options; protected $createdSession; /** * Creates a new AutoSession instance * * @param \Kirby\Session\SessionStore|string $store SessionStore object or a path to the storage directory (uses the FileSessionStore) * @param array $options Optional additional options: * - `durationNormal`: Duration of normal sessions in seconds; defaults to 2 hours * - `durationLong`: Duration of "remember me" sessions in seconds; defaults to 2 weeks * - `timeout`: Activity timeout in seconds (integer or false for none); *only* used for normal sessions; defaults to `1800` (half an hour) * - `cookieName`: Name to use for the session cookie; defaults to `kirby_session` * - `gcInterval`: How often should the garbage collector be run?; integer or `false` for never; defaults to `100` */ public function __construct($store, array $options = []) { // merge options with defaults $this->options = array_merge([ 'durationNormal' => 7200, 'durationLong' => 1209600, 'timeout' => 1800, 'cookieName' => 'kirby_session', 'gcInterval' => 100 ], $options); // create an internal instance of the low-level Sessions class $this->sessions = new Sessions($store, [ 'cookieName' => $this->options['cookieName'], 'gcInterval' => $this->options['gcInterval'] ]); } /** * Returns the automatic session * * @param array $options Optional additional options: * - `detect`: Whether to allow sessions in the `Authorization` HTTP header (`true`) or only in the session cookie (`false`); defaults to `false` * - `createMode`: When creating a new session, should it be set as a cookie or is it going to be transmitted manually to be used in a header?; defaults to `cookie` * - `long`: Whether the session is a long "remember me" session or a normal session; defaults to `false` * @return \Kirby\Session\Session */ public function get(array $options = []) { // merge options with defaults $options = array_merge([ 'detect' => false, 'createMode' => 'cookie', 'long' => false ], $options); // determine expiry options based on the session type if ($options['long'] === true) { $duration = $this->options['durationLong']; $timeout = false; } else { $duration = $this->options['durationNormal']; $timeout = $this->options['timeout']; } // get the current session if ($options['detect'] === true) { $session = $this->sessions->currentDetected(); } else { $session = $this->sessions->current(); } // create a new session if ($session === null) { $session = $this->createdSession ?? $this->sessions->create([ 'mode' => $options['createMode'], 'startTime' => time(), 'expiryTime' => time() + $duration, 'timeout' => $timeout, 'renewable' => true, ]); // cache the newly created session to ensure that we don't create multiple $this->createdSession = $session; } // update the session configuration if the $options changed // always use the less strict value for compatibility with features // that depend on the less strict behavior if ($duration > $session->duration()) { // the duration needs to be extended $session->duration($duration); } if ($session->timeout() !== false) { // a timeout exists if ($timeout === false) { // it needs to be completely disabled $session->timeout(false); } elseif (is_int($timeout) && $timeout > $session->timeout()) { // it needs to be extended $session->timeout($timeout); } } // if the session has been created and was not yet initialized, // update the mode to a custom mode // don't update back to cookie mode because the "special" behavior always wins if ($session->token() === null && $options['createMode'] !== 'cookie') { $session->mode($options['createMode']); } return $session; } /** * Creates a new empty session that is *not* automatically transmitted to the client * Useful for custom applications like a password reset link * Does *not* affect the automatic session * * @param array $options Optional additional options: * - `startTime`: Time the session starts being valid (date string or timestamp); defaults to `now` * - `expiryTime`: Time the session expires (date string or timestamp); defaults to `+ 2 hours` * - `timeout`: Activity timeout in seconds (integer or false for none); defaults to `1800` (half an hour) * - `renewable`: Should it be possible to extend the expiry date?; defaults to `true` * @return \Kirby\Session\Session */ public function createManually(array $options = []) { // only ever allow manual transmission mode // to prevent overwriting our "auto" session $options['mode'] = 'manual'; return $this->sessions->create($options); } /** * Returns the specified Session object * @since 3.3.1 * * @param string $token Session token, either including or without the key * @return \Kirby\Session\Session */ public function getManually(string $token) { return $this->sessions->get($token, 'manual'); } /** * Deletes all expired sessions * * If the `gcInterval` is configured, this is done automatically * when initializing the AutoSession class * * @return void */ public function collectGarbage() { $this->sessions->collectGarbage(); } }