refactor namespaces, start work on sql
This commit is contained in:
parent
50b78f8131
commit
8b03b209dc
|
@ -1,93 +1,96 @@
|
|||
/*
|
||||
@BLOG
|
||||
============================================================
|
||||
Stats
|
||||
============================================================
|
||||
*/
|
||||
DROP TABLE IF EXISTS blog;
|
||||
CREATE TABLE blog (
|
||||
`id` INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
`author_id` INTEGER NOT NULL,
|
||||
`title` TEXT NOT NULL,
|
||||
`slug` TEXT NOT NULL UNIQUE,
|
||||
`content` TEXT NOT NULL,
|
||||
`created` DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||||
`updated` DATETIME DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
CREATE INDEX idx_blog_author_id ON blog (`author_id`);
|
||||
CREATE INDEX idx_blog_slug ON blog (`slug`);
|
||||
CREATE TABLE stats (
|
||||
`id` INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
`luck` INTEGER NOT NULL DEFAULT 0,
|
||||
`armor` INTEGER NOT NULL DEFAULT 0,
|
||||
`focus` INTEGER NOT NULL DEFAULT 0,
|
||||
`power` INTEGER NOT NULL DEFAULT 0,
|
||||
`resist` INTEGER NOT NULL DEFAULT 0,
|
||||
`accuracy` INTEGER NOT NULL DEFAULT 0,
|
||||
`ferocity` INTEGER NOT NULL DEFAULT 0,
|
||||
`precision` INTEGER NOT NULL DEFAULT 0,
|
||||
`toughness` INTEGER NOT NULL DEFAULT 0,
|
||||
`penetration` INTEGER NOT NULL DEFAULT 0,
|
||||
) STRICT;
|
||||
|
||||
/*
|
||||
@CHARS
|
||||
============================================================
|
||||
Characters
|
||||
============================================================
|
||||
*/
|
||||
DROP TABLE IF EXISTS characters;
|
||||
CREATE TABLE characters (
|
||||
`id` INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
`user_id` INTEGER NOT NULL,
|
||||
`name` TEXT NOT NULL UNIQUE,
|
||||
`title_id` INTEGER NOT NULL DEFAULT 1,
|
||||
`level` INTEGER NOT NULL DEFAULT 1,
|
||||
`xp` INTEGER NOT NULL DEFAULT 0,
|
||||
`id` INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
`user_id` INTEGER NOT NULL,
|
||||
`name` TEXT NOT NULL UNIQUE,
|
||||
`title_id` INTEGER NOT NULL DEFAULT 1,
|
||||
`level` INTEGER NOT NULL DEFAULT 1,
|
||||
`xp` INTEGER NOT NULL DEFAULT 0,
|
||||
`xp_to_level` INTEGER NOT NULL DEFAULT 100,
|
||||
`hp` INTEGER NOT NULL DEFAULT 20,
|
||||
`m_hp` INTEGER NOT NULL DEFAULT 20,
|
||||
`mp` INTEGER NOT NULL DEFAULT 10,
|
||||
`m_mp` INTEGER NOT NULL DEFAULT 10,
|
||||
`tp` INTEGER NOT NULL DEFAULT 1,
|
||||
`m_tp` INTEGER NOT NULL DEFAULT 1,
|
||||
`pow` INTEGER NOT NULL DEFAULT 0, -- Power
|
||||
`acc` INTEGER NOT NULL DEFAULT 0, -- Accuracy
|
||||
`pen` INTEGER NOT NULL DEFAULT 0, -- Penetration
|
||||
`foc` INTEGER NOT NULL DEFAULT 0, -- Focus
|
||||
`tou` INTEGER NOT NULL DEFAULT 0, -- Toughness
|
||||
`arm` INTEGER NOT NULL DEFAULT 0, -- Armor
|
||||
`res` INTEGER NOT NULL DEFAULT 0, -- Resist
|
||||
`pre` INTEGER NOT NULL DEFAULT 0, -- Precision
|
||||
`fer` INTEGER NOT NULL DEFAULT 0, -- Ferocity
|
||||
`luck` INTEGER NOT NULL DEFAULT 0, -- Luck
|
||||
`inv_slots` INTEGER NOT NULL DEFAULT 10,
|
||||
`att_points` INTEGER NOT NULL DEFAULT 0,
|
||||
`bio` TEXT DEFAULT ''
|
||||
`hp` INTEGER NOT NULL DEFAULT 20,
|
||||
`m_hp` INTEGER NOT NULL DEFAULT 20,
|
||||
`mp` INTEGER NOT NULL DEFAULT 10,
|
||||
`m_mp` INTEGER NOT NULL DEFAULT 10,
|
||||
`tp` INTEGER NOT NULL DEFAULT 1,
|
||||
`m_tp` INTEGER NOT NULL DEFAULT 1,
|
||||
`stats_id` INTEGER NOT NULL,
|
||||
`inv_slots` INTEGER NOT NULL DEFAULT 10,
|
||||
`att_points` INTEGER NOT NULL DEFAULT 0,
|
||||
`bio` TEXT DEFAULT ''
|
||||
);
|
||||
CREATE INDEX idx_characters_user_id ON characters (`user_id`);
|
||||
|
||||
/*
|
||||
@CHARGEAR
|
||||
*/
|
||||
DROP TABLE IF EXISTS char_gear;
|
||||
CREATE TABLE char_gear (
|
||||
`char_id` INTEGER NOT NULL,
|
||||
`head` INTEGER NOT NULL DEFAULT 0,
|
||||
`chest` INTEGER NOT NULL DEFAULT 0,
|
||||
`boots` INTEGER NOT NULL DEFAULT 0,
|
||||
`hands` INTEGER NOT NULL DEFAULT 0,
|
||||
`m_hand` INTEGER NOT NULL DEFAULT 0,
|
||||
`o_hand` INTEGER NOT NULL DEFAULT 0,
|
||||
`rune` INTEGER NOT NULL DEFAULT 0,
|
||||
`ring` INTEGER NOT NULL DEFAULT 0,
|
||||
`amulet` INTEGER NOT NULL DEFAULT 0,
|
||||
`pow` INTEGER NOT NULL DEFAULT 0, -- Power
|
||||
`acc` INTEGER NOT NULL DEFAULT 0, -- Accuracy
|
||||
`pen` INTEGER NOT NULL DEFAULT 0, -- Penetration
|
||||
`foc` INTEGER NOT NULL DEFAULT 0, -- Focus
|
||||
`tou` INTEGER NOT NULL DEFAULT 0, -- Toughness
|
||||
`arm` INTEGER NOT NULL DEFAULT 0, -- Armor
|
||||
`res` INTEGER NOT NULL DEFAULT 0, -- Resist
|
||||
`pre` INTEGER NOT NULL DEFAULT 0, -- Precision
|
||||
`fer` INTEGER NOT NULL DEFAULT 0, -- Ferocity
|
||||
`luck` INTEGER NOT NULL DEFAULT 0, -- Luck
|
||||
`max_hp` INTEGER NOT NULL DEFAULT 0,
|
||||
`max_mp` INTEGER NOT NULL DEFAULT 0
|
||||
CREATE TABLE equipped_items (
|
||||
`char_id` INTEGER NOT NULL,
|
||||
`head` INTEGER NOT NULL DEFAULT 0,
|
||||
`chest` INTEGER NOT NULL DEFAULT 0,
|
||||
`boots` INTEGER NOT NULL DEFAULT 0,
|
||||
`hands` INTEGER NOT NULL DEFAULT 0,
|
||||
`m_hand` INTEGER NOT NULL DEFAULT 0,
|
||||
`o_hand` INTEGER NOT NULL DEFAULT 0,
|
||||
`rune` INTEGER NOT NULL DEFAULT 0,
|
||||
`ring` INTEGER NOT NULL DEFAULT 0,
|
||||
`amulet` INTEGER NOT NULL DEFAULT 0,
|
||||
`stats_id` INTEGER NOT NULL,
|
||||
`max_hp` INTEGER NOT NULL DEFAULT 0,
|
||||
`max_mp` INTEGER NOT NULL DEFAULT 0
|
||||
);
|
||||
CREATE INDEX idx_char_gear_char_id ON char_gear (`char_id`);
|
||||
|
||||
/*
|
||||
@CHARINV
|
||||
*/
|
||||
DROP TABLE IF EXISTS char_inventory;
|
||||
CREATE TABLE char_inventory (
|
||||
CREATE TABLE inventory_items (
|
||||
`char_id` INTEGER NOT NULL,
|
||||
`item_id` INTEGER NOT NULL
|
||||
);
|
||||
CREATE INDEX idx_inventory_char_id ON char_inventory (`char_id`);
|
||||
|
||||
-- Wallets are account-bound rather than character-bound. Should I move this to auth?
|
||||
CREATE TABLE wallets (
|
||||
`user_id` INTEGER NOT NULL,
|
||||
`silver` INTEGER NOT NULL DEFAULT 10,
|
||||
`stargem` INTEGER NOT NULL DEFAULT 0
|
||||
);
|
||||
CREATE INDEX idx_wallets_user_id ON wallets (`user_id`);
|
||||
|
||||
/*
|
||||
============================================================
|
||||
Blog
|
||||
============================================================
|
||||
*/
|
||||
create table blog (
|
||||
`id` integer primary KEY AUTOINCREMENT,
|
||||
`author_id` integer not null,
|
||||
`title` TEXT not null,
|
||||
`slug` TEXT not null unique,
|
||||
`content` TEXT not null,
|
||||
`created` DATETIME default current_timestamp,
|
||||
`updated` DATETIME default current_timestamp
|
||||
);
|
||||
CREATE INDEX idx_blog_author_id ON blog (`author_id`);
|
||||
CREATE INDEX idx_blog_slug ON blog (`slug`);
|
||||
|
||||
/*
|
||||
@WALLETS
|
||||
*/
|
||||
|
|
|
@ -1,7 +1,11 @@
|
|||
<?php
|
||||
|
||||
use Models\Character;
|
||||
|
||||
/*
|
||||
Setup
|
||||
============================================================
|
||||
Bootstrapping
|
||||
============================================================
|
||||
*/
|
||||
define('SRC', __DIR__ . '/../src');
|
||||
define('DATABASE_PATH', __DIR__ . '/../database');
|
||||
|
@ -10,7 +14,9 @@ require_once SRC . '/bootstrap.php';
|
|||
$r = new Router;
|
||||
|
||||
/*
|
||||
============================================================
|
||||
Home
|
||||
============================================================
|
||||
*/
|
||||
$r->get('/', function() {
|
||||
if (user()) redirect('/world');
|
||||
|
@ -18,73 +24,23 @@ $r->get('/', function() {
|
|||
});
|
||||
|
||||
/*
|
||||
============================================================
|
||||
Auth
|
||||
============================================================
|
||||
*/
|
||||
$r->get('/register', 'Actions\Auth::register_get')->middleware('guest_only');
|
||||
$r->post('/register', 'Actions\Auth::register_post')->middleware('guest_only');
|
||||
|
||||
$r->get('/login', function() {
|
||||
echo render('layouts/basic', ['view' => 'pages/auth/login']);
|
||||
})->middleware('guest_only');
|
||||
$r->get('/login', 'Actions\Auth::login_get')->middleware('guest_only');
|
||||
$r->post('/login', 'Actions\Auth::login_post')->middleware('guest_only');
|
||||
|
||||
$r->post('/login', function() {
|
||||
$errors = [];
|
||||
|
||||
$u = trim($_POST['u'] ?? '');
|
||||
$p = $_POST['p'] ?? '';
|
||||
|
||||
if (empty($u)) $errors['u'][] = 'Username is required.';
|
||||
if (empty($p)) $errors['p'][] = 'Password is required.';
|
||||
|
||||
// If there are errors at this point, send them to the page with errors flashed.
|
||||
if (!empty($errors)) {
|
||||
$GLOBALS['form-errors'] = $errors;
|
||||
echo render('layouts/basic', ['view' => 'pages/auth/login']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$user = User::find($u);
|
||||
if ($user === false || !$user->check_password($p)) {
|
||||
$errors['x'][] = 'Invalid username or password.';
|
||||
$GLOBALS['form-errors'] = $errors;
|
||||
echo render('layouts/basic', ['view' => 'pages/auth/login']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$_SESSION['user'] = serialize($user);
|
||||
|
||||
if ($_POST['remember'] ?? false) {
|
||||
$session = Session::create($user->id, strtotime('+30 days'));
|
||||
if ($session === false) error_response(400);
|
||||
set_cookie('remember_me', $session->token, $session->expires);
|
||||
}
|
||||
|
||||
if ($user->char_count() === 0) {
|
||||
redirect('/character/create-first');
|
||||
} elseif (!change_user_character($user->char_id)) {
|
||||
echo "failed to change user character (aclp)";
|
||||
error_response(999);
|
||||
}
|
||||
|
||||
redirect('/');
|
||||
})->middleware('guest_only');
|
||||
|
||||
$r->post('/logout', function() {
|
||||
Session::delete(user()->id);
|
||||
unset($_SESSION['user']);
|
||||
set_cookie('remember_me', '', 1);
|
||||
redirect('/');
|
||||
});
|
||||
|
||||
$r->get('/debug/logout', function() {
|
||||
Session::delete(user()->id);
|
||||
unset($_SESSION['user']);
|
||||
set_cookie('remember_me', '', 1);
|
||||
redirect('/');
|
||||
});
|
||||
$r->post('/logout', 'Actions\Auth::logout')->middleware('auth_only');
|
||||
if (env('debug', false)) $r->get('/debug/logout', 'Actions\Auth::logout');
|
||||
|
||||
/*
|
||||
============================================================
|
||||
Characters
|
||||
============================================================
|
||||
*/
|
||||
$r->get('/characters', function() {
|
||||
//echo page('chars/list', ['chars' => user()->char_list()]);
|
||||
|
@ -220,7 +176,9 @@ $r->post('/character/delete', function() {
|
|||
})->middleware('must_have_character');
|
||||
|
||||
/*
|
||||
============================================================
|
||||
World
|
||||
============================================================
|
||||
*/
|
||||
$r->get('/world', function() {
|
||||
echo render('layouts/game');
|
||||
|
@ -270,14 +228,18 @@ $r->post('/move', function() {
|
|||
})->middleware('ajax_only')->middleware('must_have_character');
|
||||
|
||||
/*
|
||||
UI
|
||||
============================================================
|
||||
UI Components
|
||||
============================================================
|
||||
*/
|
||||
$r->get('/ui/stats', function() {
|
||||
echo c_profile_stats(char());
|
||||
})->middleware('ajax_only')->middleware('must_have_character');
|
||||
|
||||
/*
|
||||
============================================================
|
||||
Router
|
||||
============================================================
|
||||
*/
|
||||
// [code, handler, params, middleware]
|
||||
$l = $r->lookup($_SERVER['REQUEST_METHOD'], $_SERVER['REQUEST_URI']);
|
||||
|
@ -287,6 +249,8 @@ if (!empty($l['middleware'])) foreach ($l['middleware'] as $middleware) $middlew
|
|||
$l['handler'](...$l['params'] ?? []);
|
||||
|
||||
/*
|
||||
============================================================
|
||||
Cleanup
|
||||
============================================================
|
||||
*/
|
||||
clear_flashes();
|
||||
|
|
|
@ -2,10 +2,17 @@
|
|||
|
||||
namespace Actions;
|
||||
|
||||
use \User;
|
||||
use Models\Session;
|
||||
use Models\User;
|
||||
use Models\Wallet;
|
||||
|
||||
class Auth
|
||||
{
|
||||
/*
|
||||
============================================================
|
||||
Registration
|
||||
============================================================
|
||||
*/
|
||||
public static function register_get(): void
|
||||
{
|
||||
echo render('layouts/basic', ['view' => 'pages/auth/register']);
|
||||
|
@ -67,10 +74,76 @@ class Auth
|
|||
exit;
|
||||
}
|
||||
|
||||
if (\User::create($u, $e, $p) === false) error_response(400);
|
||||
if (User::create($u, $e, $p) === false) error_response(400);
|
||||
|
||||
$_SESSION['user'] = serialize(\User::find($u));
|
||||
\Wallet::create(user()->id);
|
||||
$_SESSION['user'] = serialize(User::find($u));
|
||||
Wallet::create(user()->id);
|
||||
redirect('/character/create-first');
|
||||
}
|
||||
|
||||
/*
|
||||
============================================================
|
||||
Login
|
||||
============================================================
|
||||
*/
|
||||
public static function login_get(): void
|
||||
{
|
||||
echo render('layouts/basic', ['view' => 'pages/auth/login']);
|
||||
}
|
||||
|
||||
public static function login_post(): void
|
||||
{
|
||||
$errors = [];
|
||||
|
||||
$u = trim($_POST['u'] ?? '');
|
||||
$p = $_POST['p'] ?? '';
|
||||
|
||||
if (empty($u)) $errors['u'][] = 'Username is required.';
|
||||
if (empty($p)) $errors['p'][] = 'Password is required.';
|
||||
|
||||
// If there are errors at this point, send them to the page with errors flashed.
|
||||
if (!empty($errors)) {
|
||||
$GLOBALS['form-errors'] = $errors;
|
||||
echo render('layouts/basic', ['view' => 'pages/auth/login']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$user = User::find($u);
|
||||
if ($user === false || !$user->check_password($p)) {
|
||||
$errors['x'][] = 'Invalid username or password.';
|
||||
$GLOBALS['form-errors'] = $errors;
|
||||
echo render('layouts/basic', ['view' => 'pages/auth/login']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$_SESSION['user'] = serialize($user);
|
||||
|
||||
if ($_POST['remember'] ?? false) {
|
||||
$session = Session::create($user->id, strtotime('+30 days'));
|
||||
if ($session === false) error_response(400);
|
||||
set_cookie('remember_me', $session->token, $session->expires);
|
||||
}
|
||||
|
||||
if ($user->char_count() === 0) {
|
||||
redirect('/character/create-first');
|
||||
} elseif (!change_user_character($user->char_id)) {
|
||||
echo "failed to change user character (aclp)";
|
||||
error_response(999);
|
||||
}
|
||||
|
||||
redirect('/');
|
||||
}
|
||||
|
||||
/*
|
||||
============================================================
|
||||
Logout
|
||||
============================================================
|
||||
*/
|
||||
public static function logout(): void
|
||||
{
|
||||
Session::delete(user()->id);
|
||||
unset($_SESSION['user']);
|
||||
set_cookie('remember_me', '', 1);
|
||||
redirect('/');
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,13 +24,13 @@ session_start();
|
|||
============================================================
|
||||
*/
|
||||
define('CLASS_MAP', [
|
||||
'Database' => '/database.php',
|
||||
'Router' => '/router.php',
|
||||
'User' => '/models/user.php',
|
||||
'Character' => '/models/character.php',
|
||||
'Wallet' => '/models/wallet.php',
|
||||
'Session' => '/models/session.php',
|
||||
'Actions\Auth' => '/actions/auth.php',
|
||||
'Database' => '/database.php',
|
||||
'Router' => '/router.php',
|
||||
'Actions\Auth' => '/actions/auth.php',
|
||||
'Models\User' => '/models/user.php',
|
||||
'Models\Character' => '/models/character.php',
|
||||
'Models\Wallet' => '/models/wallet.php',
|
||||
'Models\Session' => '/models/session.php',
|
||||
]);
|
||||
|
||||
spl_autoload_register(function (string $class) {
|
||||
|
@ -58,12 +58,11 @@ if (env('debug', false)) {
|
|||
CSRF
|
||||
============================================================
|
||||
*/
|
||||
csrf(); // generate a CSRF token, or retrieve the current token
|
||||
csrf();
|
||||
|
||||
// error any request that fails CSRF on these methods
|
||||
if (in_array($_SERVER['REQUEST_METHOD'], ['POST', 'PUT', 'PATCH', 'DELETE'])) {
|
||||
$csrf = $_POST['csrf'] ?? $_SERVER['HTTP_X_CSRF'] ?? '';
|
||||
if (!hash_equals($_SESSION['csrf'] ?? '', $csrf)) error_response(418);
|
||||
$csrf = $_POST['csrf'] ?? $_SERVER['HTTP_X_CSRF'] ?? ''; // look for CSRF in AJAX requests
|
||||
if (!hash_equals($_SESSION['csrf'] ?? '', $csrf)) error_response(418); // I'm a Teapot
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -71,9 +70,10 @@ if (in_array($_SERVER['REQUEST_METHOD'], ['POST', 'PUT', 'PATCH', 'DELETE'])) {
|
|||
Global State
|
||||
============================================================
|
||||
*/
|
||||
$GLOBALS['databases'] = []; // database interfaces
|
||||
|
||||
// all relevant state to handling requests
|
||||
$GLOBALS['databases'] = [];
|
||||
$GLOBALS['state'] = [
|
||||
'logged_in' => isset($_SESSION['user']) || validate_session()
|
||||
'logged_in' => isset($_SESSION['user']) || validate_session(),
|
||||
'user' => null, // populated by user()
|
||||
'char' => null, // user's selected character, populated by char()
|
||||
'wallet' => null, // populated by wallet()
|
||||
];
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
<?php
|
||||
|
||||
use Models\Character;
|
||||
|
||||
/**
|
||||
* Render the logout button's form.
|
||||
*/
|
||||
|
|
|
@ -23,11 +23,7 @@ class Database extends SQLite3
|
|||
$p = strpos($query, '?') !== false;
|
||||
$stmt = $this->prepare($query);
|
||||
|
||||
if (!empty($params)) {
|
||||
foreach ($params as $k => $v) {
|
||||
$stmt->bindValue($p ? $k + 1 : $k, $v, $this->getSQLiteType($v));
|
||||
}
|
||||
}
|
||||
foreach ($params ?? [] as $k => $v) $stmt->bindValue($p ? $k + 1 : $k, $v, $this->getSQLiteType($v));
|
||||
|
||||
$start = microtime(true);
|
||||
$r = $stmt->execute();
|
||||
|
@ -61,9 +57,7 @@ class Database extends SQLite3
|
|||
$this->count++;
|
||||
$this->query_time += $time_taken;
|
||||
|
||||
if (env('debug', false)) {
|
||||
$this->log[] = [$query, $time_taken];
|
||||
}
|
||||
if (env('debug', false)) $this->log[] = [$query, $time_taken];
|
||||
}
|
||||
|
||||
private function getSQLiteType(mixed $value): int
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
<?php
|
||||
|
||||
use Models\Character;
|
||||
|
||||
/**
|
||||
* Load the environment variables from the .env file.
|
||||
*/
|
||||
|
@ -170,7 +172,7 @@ function set_cookie($name, $value, $expires)
|
|||
/**
|
||||
* Get the current user's object from SESSION if it exists.
|
||||
*/
|
||||
function user(): User|false
|
||||
function user(): Models\User|false
|
||||
{
|
||||
if (empty($_SESSION['user'])) return false;
|
||||
return $GLOBALS['state']['user'] ??= unserialize($_SESSION['user']);
|
||||
|
@ -195,8 +197,7 @@ function modify_user_session(string $field, mixed $value): bool
|
|||
function char(): Character|false
|
||||
{
|
||||
if (empty($_SESSION['user'])) return false;
|
||||
if (empty($GLOBALS['char'])) $GLOBALS['char'] = user()->current_char();
|
||||
return $GLOBALS['char'];
|
||||
return $GLOBALS['state']['char'] ??= Character::find(user()->char_id);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -233,12 +234,10 @@ function percent(float $num, float $denom, int $precision = 4): float
|
|||
* the data is up to date with every request without having to query the database every use within, for example, a
|
||||
* template. Will return false if the user or wallet does not exist.
|
||||
*/
|
||||
function wallet(): Wallet|false
|
||||
function wallet(): Models\Wallet|false
|
||||
{
|
||||
if (user() === false) return false;
|
||||
if (empty($GLOBALS['wallet'])) $w = user()->wallet();
|
||||
if ($w === false) return false;
|
||||
return $GLOBALS['wallet'] = $w;
|
||||
return $GLOBALS['state']['wallet'] = Models\Wallet::find(user()->id);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -396,7 +395,7 @@ function db_fetch_array(SQLite3Result $result, int $mode = SQLITE3_ASSOC): array
|
|||
function validate_session(): bool
|
||||
{
|
||||
if (!isset($_COOKIE['remember_me'])) return false;
|
||||
if (($session = Session::find($_COOKIE['remember_me'])) && $session->validate()) return true;
|
||||
if (($session = Models\Session::find($_COOKIE['remember_me'])) && $session->validate()) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
<?php
|
||||
|
||||
namespace Models;
|
||||
|
||||
/*
|
||||
Characters are the living, breathing entities that interact with the game world. They are inextricably linked to their
|
||||
accounts, and are the primary means by which the character interacts with the game world. Separating the character from
|
||||
|
@ -74,7 +76,7 @@ class Character
|
|||
"SELECT * FROM characters WHERE id = :id OR name = :id COLLATE NOCASE",
|
||||
[':id' => $id]
|
||||
);
|
||||
if ($q === false) throw new Exception('Failed to query character. (C::f)'); // badly formed query
|
||||
if ($q === false) throw new \Exception('Failed to query character. (C::f)'); // badly formed query
|
||||
return ($c = $q->fetchArray(SQLITE3_ASSOC)) === false ? false : new Character($c);
|
||||
}
|
||||
|
||||
|
@ -99,7 +101,7 @@ class Character
|
|||
// Create the character!
|
||||
if (live_db()->query("INSERT INTO characters ($f) VALUES ($v)", $data) === false) {
|
||||
// @TODO: Log this error
|
||||
throw new Exception('Failed to create character. (cc)');
|
||||
throw new \Exception('Failed to create character. (cc)');
|
||||
}
|
||||
|
||||
// Get the character ID
|
||||
|
@ -153,7 +155,7 @@ class Character
|
|||
"SELECT 1 FROM characters WHERE id = :i AND user_id = :u LIMIT 1",
|
||||
[':i' => $id, ':u' => $user_id]
|
||||
);
|
||||
if ($q === false) throw new Exception('Failed to query char ownership. (C::bt)');
|
||||
if ($q === false) throw new \Exception('Failed to query char ownership. (C::bt)');
|
||||
return $q->fetchArray(SQLITE3_ASSOC) !== false;
|
||||
}
|
||||
|
||||
|
@ -186,7 +188,7 @@ class Character
|
|||
{
|
||||
// Delete the character
|
||||
if (live_db()->query("DELETE FROM characters WHERE id = :p", [':p' => $id]) === false) {
|
||||
throw new Exception('Failed to delete character. (C::d)');
|
||||
throw new \Exception('Failed to delete character. (C::d)');
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -203,7 +205,7 @@ class Character
|
|||
'SELECT awarded FROM owned_titles WHERE char_id = ? AND title_id = ? LIMIT 1',
|
||||
[$this->id, $this->title_id]
|
||||
);
|
||||
if ($q === false) throw new Exception('Failed to query title. (C::t)');
|
||||
if ($q === false) throw new \Exception('Failed to query title. (C::t)');
|
||||
|
||||
$a = $q->fetchArray(SQLITE3_ASSOC);
|
||||
if ($a === false) return false;
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
<?php
|
||||
|
||||
namespace Models;
|
||||
|
||||
class Session
|
||||
{
|
||||
public function __construct(
|
||||
|
@ -29,7 +31,7 @@ class Session
|
|||
return new Session($session['user_id'], $session['token'], $session['expires']);
|
||||
}
|
||||
|
||||
public static function delete(int $user_id): SQLite3Result|false
|
||||
public static function delete(int $user_id): \SQLite3Result|false
|
||||
{
|
||||
return auth_db()->query("DELETE FROM sessions WHERE user_id = :u", [':u' => $user_id]);
|
||||
}
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
<?php
|
||||
|
||||
namespace Models;
|
||||
|
||||
/**
|
||||
* Representation of a User from the auth database. Contains auth-related info and handles meta-level state.
|
||||
*/
|
||||
|
@ -43,12 +45,12 @@ class User
|
|||
/**
|
||||
* When this account was created (registered date).
|
||||
*/
|
||||
public DateTime $created;
|
||||
public int $created;
|
||||
|
||||
/**
|
||||
* When the account was last logged in to.
|
||||
*/
|
||||
public DateTime $last_login;
|
||||
public int $last_login;
|
||||
|
||||
/**
|
||||
* Populate a User object with data; assumes you are passing the associatve array from SQLite directly.
|
||||
|
@ -57,7 +59,7 @@ class User
|
|||
{
|
||||
foreach ($data as $k => $v) {
|
||||
if (property_exists($this, $k)) {
|
||||
$this->$k = in_array($k, ['created', 'last_login']) ? new DateTime($v) : $v;
|
||||
$this->$k = in_array($k, ['created', 'last_login']) ? strtotime($v) : $v;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -72,7 +74,7 @@ class User
|
|||
"SELECT * FROM users WHERE username = :i COLLATE NOCASE OR email = :i COLLATE NOCASE OR id = :i LIMIT 1",
|
||||
[':i' => $identifier]
|
||||
);
|
||||
if ($r === false) throw new Exception("Failed to query user. (U::f)"); // badly formed query
|
||||
if ($r === false) throw new \Exception("Failed to query user. (U::f)"); // badly formed query
|
||||
$u = $r->fetchArray(SQLITE3_ASSOC);
|
||||
if ($u === false) return false; // no user found
|
||||
return new User($u);
|
||||
|
@ -83,7 +85,7 @@ class User
|
|||
* of the username or password passed to it; that is the responsibility of the caller. Returns false on
|
||||
* failure.
|
||||
*/
|
||||
public static function create(string $username, string $email, string $password, int $auth = 0): SQLite3Result|false
|
||||
public static function create(string $username, string $email, string $password, int $auth = 0): \SQLite3Result|false
|
||||
{
|
||||
return auth_db()->query("INSERT INTO users (username, email, password, auth) VALUES (:u, :e, :p, :a)", [
|
||||
':u' => $username,
|
||||
|
@ -120,7 +122,7 @@ class User
|
|||
/**
|
||||
* Delete a user by their username, email, or id.
|
||||
*/
|
||||
public static function delete(string|int $identifier): SQLite3Result|false
|
||||
public static function delete(string|int $identifier): \SQLite3Result|false
|
||||
{
|
||||
return auth_db()->query(
|
||||
"DELETE FROM users WHERE username = :i OR email = :i OR id = :i",
|
||||
|
@ -137,7 +139,7 @@ class User
|
|||
"SELECT COUNT(*) FROM characters WHERE user_id = :u",
|
||||
[':u' => $this->id]
|
||||
)->fetchArray(SQLITE3_NUM);
|
||||
if ($c === false) throw new Exception('Failed to count characters. (U::cc)');
|
||||
if ($c === false) throw new \Exception('Failed to count characters. (U::cc)');
|
||||
return (int) $c[0];
|
||||
}
|
||||
|
||||
|
@ -148,7 +150,7 @@ class User
|
|||
public function char_list(): array|false
|
||||
{
|
||||
$q = live_db()->query("SELECT id, name, level FROM characters WHERE user_id = ?", [$this->id]);
|
||||
if ($q === false) throw new Exception('Failed to list characters. (U->cl)');
|
||||
if ($q === false) throw new \Exception('Failed to list characters. (U->cl)');
|
||||
|
||||
$c = [];
|
||||
while ($row = $q->fetchArray(SQLITE3_ASSOC)) {
|
||||
|
@ -158,20 +160,4 @@ class User
|
|||
// return false if no characters
|
||||
return empty($c) ? false : $c;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the user's current Character.
|
||||
*/
|
||||
public function current_char(): Character|false
|
||||
{
|
||||
return Character::find($this->char_id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the user's wallet.
|
||||
*/
|
||||
public function wallet(): Wallet|false
|
||||
{
|
||||
return Wallet::find($this->id);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
<?php
|
||||
|
||||
namespace Models;
|
||||
|
||||
class Wallet
|
||||
{
|
||||
public function __construct(
|
||||
|
@ -11,13 +13,13 @@ class Wallet
|
|||
public static function find(int $user_id): Wallet|false
|
||||
{
|
||||
$r = live_db()->query('SELECT * FROM wallets WHERE user_id = ?', [$user_id]);
|
||||
if ($r === false) throw new Exception('Failed to query wallet. (W::f)'); // badly formed query
|
||||
if ($r === false) throw new \Exception('Failed to query wallet. (W::f)'); // badly formed query
|
||||
$w = $r->fetchArray(SQLITE3_ASSOC);
|
||||
if ($w === false) return false; // no wallet found
|
||||
return new Wallet($user_id, $w['silver'], $w['stargem']);
|
||||
}
|
||||
|
||||
public static function create(int $user_id, int $silver = -1, int $starGems = -1): SQLite3Result|false
|
||||
public static function create(int $user_id, int $silver = -1, int $starGems = -1): \SQLite3Result|false
|
||||
{
|
||||
return live_db()->query(
|
||||
"INSERT INTO wallets (user_id, silver, stargem) VALUES (:u, :s, :sg)",
|
||||
|
@ -32,7 +34,7 @@ class Wallet
|
|||
/**
|
||||
* Add a certain amount of currency to the user's wallet.
|
||||
*/
|
||||
public function give(Currency $c, int $amt): SQLite3Result|false
|
||||
public function give(\Currency $c, int $amt): \SQLite3Result|false
|
||||
{
|
||||
$cs = $c->string(true);
|
||||
$new = $this->{$cs} + $amt;
|
||||
|
@ -42,7 +44,7 @@ class Wallet
|
|||
/**
|
||||
* Remove a certain amount of currency from the user's wallet.
|
||||
*/
|
||||
public function take(Currency $c, int $amt): SQLite3Result|false
|
||||
public function take(\Currency $c, int $amt): \SQLite3Result|false
|
||||
{
|
||||
$cs = $c->string(true);
|
||||
$new = $this->{$cs} - $amt;
|
||||
|
|
Loading…
Reference in New Issue
Block a user