<?php<liu21st@gmail.com>namespace think\swoole;
use Swoole\Table;
use think\Container;
use think\facade\Cache;
use think\facade\Cookie;
use think\Session as BaseSession;
class Session extends BaseSession
{
protected $data = [];
protected $sessionName = 'PHPSESSID';
protected $expire = 0;
protected $swooleTable;
public function init(array $config = [])
{
$config = $config ?: $this->config;
if (!empty($config['name'])) {
$this->sessionName = $config['name'];
}
if (!empty($config['expire'])) {
$this->expire = $config['expire'];
}
if (!empty($config['auto_start'])) {
$this->start();
} else {
$this->init = false;
}
return $this;
}
public function boot()
{
if (is_null($this->init)) {
$this->init();
}
if (false === $this->init) {
$this->start();
}
}
public function name($name)
{
$this->sessionName = $name;
}
public function setId($id, $expire = null)
{
Cookie::set($this->sessionName, $id, $expire);
}
public function getId()
{
return Cookie::get($this->sessionName) ?: '';
}
public function set($name, $value, $prefix = null)
{
empty($this->init) && $this->boot();
$sessionId = $this->getId();
if ($sessionId) {
$this->setSession($sessionId, $name, $value);
}
}
protected function setSession($sessionId, $name, $value)
{
if (strpos($name, '.')) {
list($name1, $name2) = explode('.', $name);
$this->data[$sessionId][$name1][$name2] = $value;
} else {
$this->data[$sessionId][$name] = $value;
}
$this->writeSessionData($sessionId);
}
public function get($name = '', $prefix = null)
{
empty($this->init) && $this->boot();
$sessionId = $this->getId();
if ($sessionId) {
return $this->readSession($sessionId, $name);
}
}
protected function readSession($sessionId, $name = '')
{
$value = isset($this->data[$sessionId]) ? $this->data[$sessionId] : [];
if (!is_array($value)) {
$value = [];
}
if ('' != $name) {
$name = explode('.', $name);
foreach ($name as $val) {
if (isset($value[$val])) {
$value = $value[$val];
} else {
$value = null;
break;
}
}
}
return $value;
}
public function delete($name, $prefix = null)
{
empty($this->init) && $this->boot();
$sessionId = $this->getId();
if ($sessionId) {
$this->deleteSession($sessionId, $name);
$this->writeSessionData($sessionId);
}
}
protected function deleteSession($sessionId, $name)
{
if (is_array($name)) {
foreach ($name as $key) {
$this->deleteSession($sessionId, $key);
}
} elseif (strpos($name, '.')) {
list($name1, $name2) = explode('.', $name);
unset($this->data[$sessionId][$name1][$name2]);
} else {
unset($this->data[$sessionId][$name]);
}
}
protected function writeSessionData($sessionId)
{
if ($this->swooleTable) {
$this->swooleTable->set('sess_' . $sessionId, [
'data' => json_encode($this->data[$sessionId]),
'expire' => time() + $this->expire,
]);
} else {
Cache::set('sess_' . $sessionId, $this->data[$sessionId], $this->expire);
}
}
public function clear($prefix = null)
{
empty($this->init) && $this->boot();
$sessionId = $this->getId();
if ($sessionId) {
$this->clearSession($sessionId);
}
}
protected function clearSession($sessionId)
{
$this->data[$sessionId] = [];
if ($this->swooleTable) {
$this->swooleTable->del('sess_' . $sessionId);
} else {
Cache::rm('sess_' . $sessionId);
}
}
public function has($name, $prefix = null)
{
empty($this->init) && $this->boot();
$sessionId = $this->getId();
if ($sessionId) {
return $this->hasSession($sessionId, $name);
}
return false;
}
protected function hasSession($sessionId, $name)
{
$value = isset($this->data[$sessionId]) ? $this->data[$sessionId] : [];
$name = explode('.', $name);
foreach ($name as $val) {
if (!isset($value[$val])) {
return false;
} else {
$value = $value[$val];
}
}
return true;
}
public function start()
{
$sessionId = $this->getId();
if (!$sessionId) {
$sessionId = $this->regenerate();
}
if (empty($this->data[$sessionId])) {
if (!empty($this->config['use_swoole_table'])) {
$this->swooleTable = Container::get('swoole_table');
$result = $this->swooleTable->get('sess_' . $sessionId);
if (0 == $result['expire'] || time() <= $result['expire']) {
$data = $result['data'];
}
} else {
$data = Cache::get('sess_' . $sessionId);
}
if (!empty($data)) {
$this->data[$sessionId] = $data;
}
}
$this->init = true;
}
public function destroy()
{
$sessionId = $this->getId();
if ($sessionId) {
$this->destroySession($sessionId);
}
$this->init = null;
}
protected function destroySession($sessionId)
{
if (isset($this->data[$sessionId])) {
unset($this->data[$sessionId]);
if ($this->swooleTable) {
$this->swooleTable->del('sess_' . $sessionId);
} else {
Cache::rm('sess_' . $sessionId);
}
}
}
public function regenerate($delete = false)
{
if ($delete) {
$this->destroy();
}
$sessionId = md5(microtime(true) . uniqid());
$this->setId($sessionId);
return $sessionId;
}
public function pause()
{
$this->init = false;
}
}