123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295 |
- <?php
-
- namespace Illuminate\Session;
-
- use Illuminate\Support\Arr;
- use SessionHandlerInterface;
- use Illuminate\Support\Carbon;
- use Illuminate\Contracts\Auth\Guard;
- use Illuminate\Database\QueryException;
- use Illuminate\Support\InteractsWithTime;
- use Illuminate\Database\ConnectionInterface;
- use Illuminate\Contracts\Container\Container;
-
- class DatabaseSessionHandler implements SessionHandlerInterface, ExistenceAwareInterface
- {
- use InteractsWithTime;
-
- /**
- * The database connection instance.
- *
- * @var \Illuminate\Database\ConnectionInterface
- */
- protected $connection;
-
- /**
- * The name of the session table.
- *
- * @var string
- */
- protected $table;
-
- /**
- * The number of minutes the session should be valid.
- *
- * @var int
- */
- protected $minutes;
-
- /**
- * The container instance.
- *
- * @var \Illuminate\Contracts\Container\Container
- */
- protected $container;
-
- /**
- * The existence state of the session.
- *
- * @var bool
- */
- protected $exists;
-
- /**
- * Create a new database session handler instance.
- *
- * @param \Illuminate\Database\ConnectionInterface $connection
- * @param string $table
- * @param int $minutes
- * @param \Illuminate\Contracts\Container\Container|null $container
- * @return void
- */
- public function __construct(ConnectionInterface $connection, $table, $minutes, Container $container = null)
- {
- $this->table = $table;
- $this->minutes = $minutes;
- $this->container = $container;
- $this->connection = $connection;
- }
-
- /**
- * {@inheritdoc}
- */
- public function open($savePath, $sessionName)
- {
- return true;
- }
-
- /**
- * {@inheritdoc}
- */
- public function close()
- {
- return true;
- }
-
- /**
- * {@inheritdoc}
- */
- public function read($sessionId)
- {
- $session = (object) $this->getQuery()->find($sessionId);
-
- if ($this->expired($session)) {
- $this->exists = true;
-
- return '';
- }
-
- if (isset($session->payload)) {
- $this->exists = true;
-
- return base64_decode($session->payload);
- }
-
- return '';
- }
-
- /**
- * Determine if the session is expired.
- *
- * @param \stdClass $session
- * @return bool
- */
- protected function expired($session)
- {
- return isset($session->last_activity) &&
- $session->last_activity < Carbon::now()->subMinutes($this->minutes)->getTimestamp();
- }
-
- /**
- * {@inheritdoc}
- */
- public function write($sessionId, $data)
- {
- $payload = $this->getDefaultPayload($data);
-
- if (! $this->exists) {
- $this->read($sessionId);
- }
-
- if ($this->exists) {
- $this->performUpdate($sessionId, $payload);
- } else {
- $this->performInsert($sessionId, $payload);
- }
-
- return $this->exists = true;
- }
-
- /**
- * Perform an insert operation on the session ID.
- *
- * @param string $sessionId
- * @param string $payload
- * @return bool|null
- */
- protected function performInsert($sessionId, $payload)
- {
- try {
- return $this->getQuery()->insert(Arr::set($payload, 'id', $sessionId));
- } catch (QueryException $e) {
- $this->performUpdate($sessionId, $payload);
- }
- }
-
- /**
- * Perform an update operation on the session ID.
- *
- * @param string $sessionId
- * @param string $payload
- * @return int
- */
- protected function performUpdate($sessionId, $payload)
- {
- return $this->getQuery()->where('id', $sessionId)->update($payload);
- }
-
- /**
- * Get the default payload for the session.
- *
- * @param string $data
- * @return array
- */
- protected function getDefaultPayload($data)
- {
- $payload = [
- 'payload' => base64_encode($data),
- 'last_activity' => $this->currentTime(),
- ];
-
- if (! $this->container) {
- return $payload;
- }
-
- return tap($payload, function (&$payload) {
- $this->addUserInformation($payload)
- ->addRequestInformation($payload);
- });
- }
-
- /**
- * Add the user information to the session payload.
- *
- * @param array $payload
- * @return $this
- */
- protected function addUserInformation(&$payload)
- {
- if ($this->container->bound(Guard::class)) {
- $payload['user_id'] = $this->userId();
- }
-
- return $this;
- }
-
- /**
- * Get the currently authenticated user's ID.
- *
- * @return mixed
- */
- protected function userId()
- {
- return $this->container->make(Guard::class)->id();
- }
-
- /**
- * Add the request information to the session payload.
- *
- * @param array $payload
- * @return $this
- */
- protected function addRequestInformation(&$payload)
- {
- if ($this->container->bound('request')) {
- $payload = array_merge($payload, [
- 'ip_address' => $this->ipAddress(),
- 'user_agent' => $this->userAgent(),
- ]);
- }
-
- return $this;
- }
-
- /**
- * Get the IP address for the current request.
- *
- * @return string
- */
- protected function ipAddress()
- {
- return $this->container->make('request')->ip();
- }
-
- /**
- * Get the user agent for the current request.
- *
- * @return string
- */
- protected function userAgent()
- {
- return substr((string) $this->container->make('request')->header('User-Agent'), 0, 500);
- }
-
- /**
- * {@inheritdoc}
- */
- public function destroy($sessionId)
- {
- $this->getQuery()->where('id', $sessionId)->delete();
-
- return true;
- }
-
- /**
- * {@inheritdoc}
- */
- public function gc($lifetime)
- {
- $this->getQuery()->where('last_activity', '<=', $this->currentTime() - $lifetime)->delete();
- }
-
- /**
- * Get a fresh query builder instance for the table.
- *
- * @return \Illuminate\Database\Query\Builder
- */
- protected function getQuery()
- {
- return $this->connection->table($this->table);
- }
-
- /**
- * Set the existence state for the session.
- *
- * @param bool $value
- * @return $this
- */
- public function setExists($value)
- {
- $this->exists = $value;
-
- return $this;
- }
- }
|