refactor
This commit is contained in:
parent
944b6b0526
commit
1f04b83be3
50 changed files with 965 additions and 491 deletions
|
@ -5,7 +5,8 @@ CREATE VIEW api.post AS
|
||||||
p.content,
|
p.content,
|
||||||
p.date
|
p.date
|
||||||
FROM
|
FROM
|
||||||
admin.post p;
|
admin.post p
|
||||||
|
ORDER BY id DESC;
|
||||||
|
|
||||||
GRANT SELECT ON TABLE api.post
|
GRANT SELECT ON TABLE api.post
|
||||||
TO rest_anon, rest_user;
|
TO rest_anon, rest_user;
|
||||||
|
|
|
@ -32,6 +32,8 @@ GRANT INSERT ON TABLE api.post
|
||||||
TO rest_user;
|
TO rest_user;
|
||||||
GRANT INSERT ON TABLE admin.post
|
GRANT INSERT ON TABLE admin.post
|
||||||
TO rest_user;
|
TO rest_user;
|
||||||
|
GRANT UPDATE ON TABLE sys.post_id_seq
|
||||||
|
TO rest_user;
|
||||||
|
|
||||||
CREATE TRIGGER api_post_insert_trgr
|
CREATE TRIGGER api_post_insert_trgr
|
||||||
INSTEAD OF INSERT
|
INSTEAD OF INSERT
|
||||||
|
|
|
@ -29,7 +29,7 @@ BEGIN
|
||||||
|
|
||||||
IF _min IS NOT NULL AND _length < _min THEN
|
IF _min IS NOT NULL AND _length < _min THEN
|
||||||
PERFORM _api.raise(
|
PERFORM _api.raise(
|
||||||
_msg => 'api_text_min',
|
_msg => 'api_min_value',
|
||||||
_detail => _column,
|
_detail => _column,
|
||||||
_hint => _min || ''
|
_hint => _min || ''
|
||||||
);
|
);
|
||||||
|
@ -37,7 +37,7 @@ BEGIN
|
||||||
|
|
||||||
IF _max IS NOT NULL AND _length > _max THEN
|
IF _max IS NOT NULL AND _length > _max THEN
|
||||||
PERFORM _api.raise(
|
PERFORM _api.raise(
|
||||||
_msg => 'api_text_max',
|
_msg => 'api_max_value',
|
||||||
_detail => _column,
|
_detail => _column,
|
||||||
_hint => _max || ''
|
_hint => _max || ''
|
||||||
);
|
);
|
||||||
|
|
23
web/_controller/_index.php
Normal file
23
web/_controller/_index.php
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
<?php /* Copyright (c) 2024 Freya Murphy */
|
||||||
|
class _index_controller extends Controller {
|
||||||
|
|
||||||
|
// the home model
|
||||||
|
private $home_model;
|
||||||
|
|
||||||
|
// the request model
|
||||||
|
private $request_model;
|
||||||
|
|
||||||
|
// the caceh model
|
||||||
|
private $cache_model;
|
||||||
|
|
||||||
|
public function index(): void {
|
||||||
|
if ($this->main->session) {
|
||||||
|
$this->redirect('/home');
|
||||||
|
} else {
|
||||||
|
$this->redirect('/login');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
?>
|
20
web/_controller/apps/error.php
Normal file
20
web/_controller/apps/error.php
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
<?php /* Copyright (c) 2024 Freya Murphy */
|
||||||
|
class Error_controller extends Controller {
|
||||||
|
|
||||||
|
private $error_model;
|
||||||
|
|
||||||
|
function __construct($load) {
|
||||||
|
parent::__construct($load);
|
||||||
|
$this->error_model = $this->load->model('apps/error');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function index() {
|
||||||
|
parent::index();
|
||||||
|
$data = $this->error_model->get_data();
|
||||||
|
$this->view('header', $data);
|
||||||
|
$this->view('apps/error/main', $data);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
?>
|
|
@ -1,22 +1,31 @@
|
||||||
<?php /* Copyright (c) 2024 Freya Murphy */
|
<?php /* Copyright (c) 2024 Freya Murphy */
|
||||||
class HomeController extends Controller {
|
class Home_controller extends Controller {
|
||||||
|
|
||||||
private $model;
|
// the home model
|
||||||
|
private $home_model;
|
||||||
|
|
||||||
function __construct($model) {
|
// the request model
|
||||||
parent::__construct();
|
private $request_model;
|
||||||
$this->model = $model;
|
|
||||||
|
// the caceh model
|
||||||
|
private $cache_model;
|
||||||
|
|
||||||
|
function __construct($load) {
|
||||||
|
parent::__construct($load);
|
||||||
|
$this->home_model = $this->load->model('apps/home');
|
||||||
|
$this->request_model = $this->load->model('request');
|
||||||
|
$this->cache_model = $this->load->model('cache');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function index() {
|
public function index(): void {
|
||||||
parent::index();
|
parent::index();
|
||||||
$data = $this->model->get_data();
|
$data = $this->home_model->get_data();
|
||||||
$this->view('header', $data);
|
$this->view('header', $data);
|
||||||
$this->app_view('main', $data);
|
$this->view('apps/home/main', $data);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function posts() {
|
public function posts(): void {
|
||||||
$page = $this->main->get_num('page', 0);
|
$page = $this->request_model->get_int('page', 0);
|
||||||
$page_size = 20;
|
$page_size = 20;
|
||||||
$offset = $page * $page_size;
|
$offset = $page * $page_size;
|
||||||
|
|
||||||
|
@ -30,7 +39,7 @@ class HomeController extends Controller {
|
||||||
$query = $query->select('p.*, FALSE as liked');
|
$query = $query->select('p.*, FALSE as liked');
|
||||||
}
|
}
|
||||||
|
|
||||||
$query = $query->from('admin.post p');
|
$query = $query->from('api.post p');
|
||||||
|
|
||||||
if ($user) {
|
if ($user) {
|
||||||
$query = $query->join('admin.like l', 'p.id = l.post_id')
|
$query = $query->join('admin.like l', 'p.id = l.post_id')
|
||||||
|
@ -42,7 +51,7 @@ class HomeController extends Controller {
|
||||||
->offset($offset)
|
->offset($offset)
|
||||||
->rows();
|
->rows();
|
||||||
|
|
||||||
$users = $this->main->get_users($posts);
|
$users = $this->cache_model->get_users($posts);
|
||||||
|
|
||||||
foreach ($posts as $post) {
|
foreach ($posts as $post) {
|
||||||
$data = array();
|
$data = array();
|
||||||
|
@ -52,9 +61,9 @@ class HomeController extends Controller {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function comments() {
|
public function comments(): void {
|
||||||
$page = $this->main->get_num('page', 0);
|
$page = $this->request_model->get_int('page', 0);
|
||||||
$id = $this->main->get_num('id');
|
$id = $this->request_model->get_int('id');
|
||||||
$page_size = 20;
|
$page_size = 20;
|
||||||
$offset = $page * $page_size;
|
$offset = $page * $page_size;
|
||||||
|
|
||||||
|
@ -65,7 +74,7 @@ class HomeController extends Controller {
|
||||||
->offset($offset)
|
->offset($offset)
|
||||||
->rows();
|
->rows();
|
||||||
|
|
||||||
$users = $this->main->get_users($comments);
|
$users = $this->cache_model->get_users($comments);
|
||||||
|
|
||||||
foreach ($comments as $comment) {
|
foreach ($comments as $comment) {
|
||||||
$data = array();
|
$data = array();
|
||||||
|
@ -75,10 +84,6 @@ class HomeController extends Controller {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function new_post_modal() {
|
|
||||||
$this->modal(lang('new_post_modal_title'), 'new-post');
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
?>
|
?>
|
26
web/_controller/modal.php
Normal file
26
web/_controller/modal.php
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
<?php /* Copyright (c) 2024 Freya Murphy */
|
||||||
|
class Modal_controller extends Controller {
|
||||||
|
|
||||||
|
|
||||||
|
function __construct($load) {
|
||||||
|
parent::__construct($load);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $name
|
||||||
|
* @param array $data
|
||||||
|
*/
|
||||||
|
private function modal($name, $data = array()): void {
|
||||||
|
$title = lang($name . '_modal_title');
|
||||||
|
$data['title'] = $title;
|
||||||
|
$data['content'] = $name;
|
||||||
|
$this->view('template/modal', $data);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function new_post(): void {
|
||||||
|
$this->modal('new_post');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
?>
|
||||||
|
|
22
web/_controller/template.php
Normal file
22
web/_controller/template.php
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
<?php /* Copyright (c) 2024 Freya Murphy */
|
||||||
|
class Template_controller extends Controller {
|
||||||
|
|
||||||
|
// the request model
|
||||||
|
private $request_model;
|
||||||
|
|
||||||
|
function __construct($load) {
|
||||||
|
parent::__construct($load);
|
||||||
|
$this->request_model = $this->load->model('request');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function toast(): void {
|
||||||
|
$data = array(
|
||||||
|
'msg' => $this->request_model->get_str('msg', FALSE),
|
||||||
|
'detail' => $this->request_model->get_str('detail', FALSE),
|
||||||
|
'hint' => $this->request_model->get_str('hint', FALSE)
|
||||||
|
);
|
||||||
|
$this->view('template/toast', $data);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
|
@ -1,5 +1,9 @@
|
||||||
<?php /* Copyright (c) 2024 Freya Murphy */
|
<?php /* Copyright (c) 2024 Freya Murphy */
|
||||||
class ErrorModel extends Model {
|
class Error_model extends Model {
|
||||||
|
|
||||||
|
function __construct($load) {
|
||||||
|
parent::__construct($load);
|
||||||
|
}
|
||||||
|
|
||||||
private function get_msg(&$data) {
|
private function get_msg(&$data) {
|
||||||
if (!array_key_exists('code', $_GET)) {
|
if (!array_key_exists('code', $_GET)) {
|
||||||
|
@ -22,7 +26,7 @@ class ErrorModel extends Model {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function get_data() {
|
public function get_data(): array {
|
||||||
$data = parent::get_data();
|
$data = parent::get_data();
|
||||||
$this->get_msg($data);
|
$this->get_msg($data);
|
||||||
return $data;
|
return $data;
|
|
@ -1,7 +1,11 @@
|
||||||
<?php /* Copyright (c) 2024 Freya Murphy */
|
<?php /* Copyright (c) 2024 Freya Murphy */
|
||||||
class HomeModel extends Model {
|
class Home_model extends Model {
|
||||||
|
|
||||||
private function get_posts() {
|
function __construct($load) {
|
||||||
|
parent::__construct($load);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function get_posts(): array {
|
||||||
return $this->db
|
return $this->db
|
||||||
->select('*')
|
->select('*')
|
||||||
->from('admin.post')
|
->from('admin.post')
|
||||||
|
@ -9,11 +13,10 @@ class HomeModel extends Model {
|
||||||
->rows();
|
->rows();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function get_data() {
|
public function get_data(): array {
|
||||||
$data = parent::get_data();
|
$data = parent::get_data();
|
||||||
$data['title'] = lang('title');
|
$data['title'] = lang('title');
|
||||||
$data['posts'] = $this->get_posts();
|
$data['posts'] = $this->get_posts();
|
||||||
return $data;
|
return $data;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
?>
|
|
37
web/_model/cache.php
Normal file
37
web/_model/cache.php
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
<?php /* Copyright (c) 2024 Freya Murphy */
|
||||||
|
class Cache_model extends Model {
|
||||||
|
|
||||||
|
// the user cache
|
||||||
|
private $users;
|
||||||
|
|
||||||
|
function __construct($load) {
|
||||||
|
parent::__construct($load);
|
||||||
|
$this->users = array();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets a array of users
|
||||||
|
*/
|
||||||
|
public function get_users($objs) {
|
||||||
|
$ids = array();
|
||||||
|
foreach ($objs as $obj) {
|
||||||
|
$id = $obj['user_id'];
|
||||||
|
if (!array_key_exists($id, $this->users)) {
|
||||||
|
array_push($ids, intval($id));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!empty($ids)) {
|
||||||
|
$result = $this->main->db
|
||||||
|
->select('*')
|
||||||
|
->from('api.user')
|
||||||
|
->where_in('id', $ids)
|
||||||
|
->rows();
|
||||||
|
foreach ($result as $user) {
|
||||||
|
$id = $user['id'];
|
||||||
|
$this->users[$id] = $user;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $this->users;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
45
web/_model/format.php
Normal file
45
web/_model/format.php
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
<?php /* Copyright (c) 2024 Freya Murphy */
|
||||||
|
class Format_model extends Modal {
|
||||||
|
|
||||||
|
function __construct($load) {
|
||||||
|
parent::__construct($load);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Formats a users's name
|
||||||
|
* @param array $user - the $user
|
||||||
|
* @returns the user's formatted display name
|
||||||
|
*/
|
||||||
|
public function name($user) {
|
||||||
|
$name = '';
|
||||||
|
if ($user['first_name']) {
|
||||||
|
$name .= $user['first_name'];
|
||||||
|
}
|
||||||
|
if ($user['middle_name']) {
|
||||||
|
if ($name != '') {
|
||||||
|
$name .= ' ';
|
||||||
|
}
|
||||||
|
$name .= $user['middle_name'];
|
||||||
|
}
|
||||||
|
if ($user['last_name']) {
|
||||||
|
if ($name != '') {
|
||||||
|
$name .= ' ';
|
||||||
|
}
|
||||||
|
$name .= $user['last_name'];
|
||||||
|
}
|
||||||
|
if ($name == '') {
|
||||||
|
$name = '@' . $user['username'];
|
||||||
|
}
|
||||||
|
return $name;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Formats a date
|
||||||
|
* @param string $date - the data in RFC3999 format
|
||||||
|
* @returns the formatted date
|
||||||
|
*/
|
||||||
|
public function date($date) {
|
||||||
|
return $date;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
84
web/_model/main.php
Normal file
84
web/_model/main.php
Normal file
|
@ -0,0 +1,84 @@
|
||||||
|
<?php /* Copyright (c) 2024 Freya Murphy */
|
||||||
|
class Main_model {
|
||||||
|
|
||||||
|
// the website database
|
||||||
|
public $db;
|
||||||
|
|
||||||
|
// the current user session (can be NULL)
|
||||||
|
public $session;
|
||||||
|
|
||||||
|
// current loaded users
|
||||||
|
private $users;
|
||||||
|
|
||||||
|
// stores the current request info
|
||||||
|
public $info;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loads the main model
|
||||||
|
* @param Loader $load - the main loader object
|
||||||
|
*/
|
||||||
|
function __construct($load) {
|
||||||
|
/// load the database helper
|
||||||
|
$this->db = new DatabaseHelper();
|
||||||
|
/// load the current session
|
||||||
|
if (array_key_exists('jwt', $_SESSION)) {
|
||||||
|
$this->get_session($_SESSION['jwt']);
|
||||||
|
} else {
|
||||||
|
$this->session = NULL;
|
||||||
|
};
|
||||||
|
/// init other vars
|
||||||
|
$this->users = array();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loads current session
|
||||||
|
* @param string $jwt - the user provided JWT
|
||||||
|
*/
|
||||||
|
private function get_session($jwt) {
|
||||||
|
$query = $this->db
|
||||||
|
->select("_api.verify_jwt('" . $jwt . "') AS user_id;");
|
||||||
|
$result = $query->row();
|
||||||
|
$user_id = $result['user_id'];
|
||||||
|
if ($user_id) {
|
||||||
|
$this->session = array(
|
||||||
|
'id' => $user_id,
|
||||||
|
'jwt' => $jwt
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loads a css html link
|
||||||
|
* @param string $path - the path to the css file
|
||||||
|
*/
|
||||||
|
public function link_css($path) {
|
||||||
|
return '<link rel="stylesheet" href="/public/' . $path . '">';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loads a js html link
|
||||||
|
* @param string $path - the path to the js file
|
||||||
|
*/
|
||||||
|
public function link_js($path) {
|
||||||
|
return '<script src="/public/'. $path . '"></script>';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the current user
|
||||||
|
*/
|
||||||
|
public function user() {
|
||||||
|
if ($this->session) {
|
||||||
|
return $this->db
|
||||||
|
->select('*')
|
||||||
|
->from('api.user')
|
||||||
|
->where('id')
|
||||||
|
->eq($this->session['id'])
|
||||||
|
->row();
|
||||||
|
} else {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
?>
|
40
web/_model/request.php
Normal file
40
web/_model/request.php
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
<?php /* Copyright (c) 2024 Freya Murphy */
|
||||||
|
class Request_model extends Model {
|
||||||
|
|
||||||
|
function __construct($load) {
|
||||||
|
parent::__construct($load);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loads a string from the GET request
|
||||||
|
* @param string $key - the name for the query param
|
||||||
|
* @param string $default - the default value if not exists
|
||||||
|
*/
|
||||||
|
public function get_str($key, $default = NULL): string | NULL {
|
||||||
|
if (!array_key_exists($key, $_GET)) {
|
||||||
|
return $default;
|
||||||
|
} else {
|
||||||
|
return $_GET[$key];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loads a number from the GET request
|
||||||
|
* @param string $key - the name for the query param
|
||||||
|
* @param int $default - the default value if not exists
|
||||||
|
*/
|
||||||
|
public function get_int($key, $default = NULL): int | NULL {
|
||||||
|
if (!array_key_exists($key, $_GET)) {
|
||||||
|
return $default;
|
||||||
|
} else {
|
||||||
|
$val = $_GET[$key];
|
||||||
|
$val = intval($val);
|
||||||
|
if ($val < 0) {
|
||||||
|
return 0;
|
||||||
|
} else {
|
||||||
|
return $val;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -9,7 +9,7 @@ class Aesthetic {
|
||||||
'js' => [
|
'js' => [
|
||||||
'js/jquery-3.7.1.min.js',
|
'js/jquery-3.7.1.min.js',
|
||||||
'js/lib.js',
|
'js/lib.js',
|
||||||
'js/modal.js',
|
'js/shared/modal.js',
|
||||||
],
|
],
|
||||||
'css' => [
|
'css' => [
|
||||||
'css/common.css'
|
'css/common.css'
|
||||||
|
@ -22,7 +22,8 @@ class Aesthetic {
|
||||||
),
|
),
|
||||||
'home' => array(
|
'home' => array(
|
||||||
'js' => [
|
'js' => [
|
||||||
'js/post.js',
|
'js/shared/post.js',
|
||||||
|
'js/routes/home.js',
|
||||||
],
|
],
|
||||||
'css' => [
|
'css' => [
|
||||||
'css/home.css',
|
'css/home.css',
|
7
web/config/routes.php
Normal file
7
web/config/routes.php
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
<?php /* Copyright (c) 2024 Freya Murphy */
|
||||||
|
|
||||||
|
$routes = array();
|
||||||
|
$routes['home'] = 'apps/home';
|
||||||
|
$routes['error'] = 'apps/error';
|
||||||
|
|
||||||
|
$routes[''] = '_index';
|
49
web/core/_controller.php
Normal file
49
web/core/_controller.php
Normal file
|
@ -0,0 +1,49 @@
|
||||||
|
<?php /* Copyright (c) 2024 Freya Murphy */
|
||||||
|
abstract class Controller {
|
||||||
|
|
||||||
|
// the main model
|
||||||
|
public $main;
|
||||||
|
|
||||||
|
// the loader
|
||||||
|
public $load;
|
||||||
|
|
||||||
|
// the database
|
||||||
|
public $db;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a constructor
|
||||||
|
* @param Loader $load - the website loaded object
|
||||||
|
*/
|
||||||
|
function __construct($load) {
|
||||||
|
$this->load = $load;
|
||||||
|
$this->main = $this->load->model('main');
|
||||||
|
$this->db = $this->main->db;
|
||||||
|
|
||||||
|
$info = $this->main->info;
|
||||||
|
$lang = $info['lang'];
|
||||||
|
$this->load->lang($lang);
|
||||||
|
$app = $info['app'];
|
||||||
|
if ($app) {
|
||||||
|
$this->load->app_lang($lang, $app);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function index() {}
|
||||||
|
|
||||||
|
public function redirect($link) {
|
||||||
|
header('Location: '. $link, true, 301);
|
||||||
|
die();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function view($__name, $data = array()) {
|
||||||
|
$__root = $GLOBALS['webroot'];
|
||||||
|
$__path = $__root . '/views/' . $__name . '.php';
|
||||||
|
if (is_file($__path)) {
|
||||||
|
extract($data);
|
||||||
|
require($__path);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
?>
|
44
web/core/_model.php
Normal file
44
web/core/_model.php
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
<?php /* Copyright (c) 2024 Freya Murphy */
|
||||||
|
abstract class Model {
|
||||||
|
// the main model
|
||||||
|
// shared by all controllers and models
|
||||||
|
public $main;
|
||||||
|
public $load;
|
||||||
|
|
||||||
|
// the database
|
||||||
|
public $db;
|
||||||
|
|
||||||
|
private $config;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a model
|
||||||
|
* @param Loader $load - the main loader object
|
||||||
|
*/
|
||||||
|
function __construct($load) {
|
||||||
|
$this->load = $load;
|
||||||
|
$this->main = $this->load->model('main');
|
||||||
|
$this->db = $this->main->db;
|
||||||
|
$this->config = new Aesthetic();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @returns the base model data
|
||||||
|
*/
|
||||||
|
public function get_data(): array {
|
||||||
|
$data = array();
|
||||||
|
$data['self'] = $this->main->user();
|
||||||
|
|
||||||
|
$info = $this->main->info;
|
||||||
|
$app = $info['app'];
|
||||||
|
|
||||||
|
if ($app) {
|
||||||
|
$files = $this->config->get_files($app);
|
||||||
|
$data = array_merge($data, $files);
|
||||||
|
} else {
|
||||||
|
$files = $this->config->get_files();
|
||||||
|
$data = array_merge($data, $files);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $data;
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,55 +0,0 @@
|
||||||
<?php /* Copyright (c) 2024 Freya Murphy */
|
|
||||||
abstract class Controller {
|
|
||||||
|
|
||||||
// the main model
|
|
||||||
public $main;
|
|
||||||
|
|
||||||
// the loader
|
|
||||||
public $load;
|
|
||||||
|
|
||||||
// the database
|
|
||||||
public $db;
|
|
||||||
|
|
||||||
function __construct() {
|
|
||||||
$this->main = $GLOBALS['__vars']['main'];
|
|
||||||
$this->load = $GLOBALS['__vars']['load'];
|
|
||||||
$this->db = $this->main->db;
|
|
||||||
|
|
||||||
$info = $this->main->info;
|
|
||||||
$lang_code = $info['lang'];
|
|
||||||
$route_name = $info['route'];
|
|
||||||
$this->load->lang($lang_code);
|
|
||||||
$this->load->route_lang($lang_code, $route_name);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function index() {}
|
|
||||||
|
|
||||||
protected function view($__name, $data = array()) {
|
|
||||||
$__root = $GLOBALS['webroot'];
|
|
||||||
$__path = $__root . '/views/' . $__name . '.php';
|
|
||||||
if (is_file($__path)) {
|
|
||||||
extract($data);
|
|
||||||
require($__path);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected function app_view($__name, $data = array()) {
|
|
||||||
$__root = $GLOBALS['webroot'];
|
|
||||||
$__route = $this->main->info['route'];
|
|
||||||
$__path = $__root . '/routes/' . $__route . '/views/' . $__name . '.php';
|
|
||||||
if (is_file($__path)) {
|
|
||||||
extract($data);
|
|
||||||
require($__path);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected function modal($title, $content, $data = array()) {
|
|
||||||
$data['title'] = $title;
|
|
||||||
$data['content'] = $content;
|
|
||||||
$this->view('template/modal', $data);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
?>
|
|
|
@ -170,4 +170,3 @@ class DatabaseHelper {
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
?>
|
|
||||||
|
|
|
@ -1,16 +1,79 @@
|
||||||
<?php /* Copyright (c) 2024 Freya Murphy */
|
<?php /* Copyright (c) 2024 Freya Murphy */
|
||||||
class Loader {
|
class Loader {
|
||||||
|
|
||||||
|
// keep track of what has been loaded
|
||||||
|
private $loaded;
|
||||||
|
|
||||||
|
function __construct() {
|
||||||
|
$this->loaded = array();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loads a $type of object from a $dir with a given $name
|
||||||
|
* @param string $name - the name of the object to load
|
||||||
|
* @param string $dir - the directory theese objects are stored in
|
||||||
|
* @param string $type - the type of the object
|
||||||
|
*/
|
||||||
|
private function load_type($name, $dir, $type): object|NULL {
|
||||||
|
$path = $dir . '/' . $name . '.php';
|
||||||
|
if (array_key_exists($path, $this->loaded)) {
|
||||||
|
return $this->loaded[$path];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!file_exists($path)) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
$parts = explode('/', $name);
|
||||||
|
$part = end($parts);
|
||||||
|
$class = ucfirst($part) . '_' . $type;
|
||||||
|
require($path);
|
||||||
|
|
||||||
|
$ref = NULL;
|
||||||
|
try {
|
||||||
|
$ref = new ReflectionClass($class);
|
||||||
|
} catch (Exception $_e) {}
|
||||||
|
|
||||||
|
if ($ref === NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
$obj = $ref->newInstance($this);
|
||||||
|
$this->loaded[$path] = $obj;
|
||||||
|
|
||||||
|
return $obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loads a model
|
||||||
|
* @param string $name - the name of the model to load
|
||||||
|
*/
|
||||||
|
public function model($name): object|NULL {
|
||||||
|
$root = $GLOBALS['webroot'];
|
||||||
|
$dir = $root . '/_model';
|
||||||
|
return $this->load_type($name, $dir, 'model');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loads a controller
|
||||||
|
* @param string $name - the name of the controller to load
|
||||||
|
*/
|
||||||
|
public function controller($name): Controller|NULL {
|
||||||
|
$root = $GLOBALS['webroot'];
|
||||||
|
$dir = $root . '/_controller';
|
||||||
|
return $this->load_type($name, $dir, 'controller');
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Loads the given common lang
|
* Loads the given common lang
|
||||||
* @param lang_code - the language code
|
* @param string $lang_code 0 the language code
|
||||||
*/
|
*/
|
||||||
public function lang($lang_code) {
|
public function lang($lang_code): void {
|
||||||
$dir = $GLOBALS['webroot'] . '/lang/' . $lang_code . '/';
|
$dir = $GLOBALS['webroot'] . '/lang/' . $lang_code . '/';
|
||||||
$lang = $GLOBALS['lang'];
|
$lang = $GLOBALS['lang'];
|
||||||
if ($handle = opendir($dir)) {
|
if ($handle = opendir($dir)) {
|
||||||
while (false !== ($entry = readdir($handle))) {
|
while (false !== ($entry = readdir($handle))) {
|
||||||
if ($entry === '.' || $entry === '..' || $entry === 'routes') {
|
if ($entry === '.' || $entry === '..' || $entry === 'apps') {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
$path = $dir . $entry;
|
$path = $dir . $entry;
|
||||||
|
@ -21,12 +84,12 @@ class Loader {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Loads a given route specific lang
|
* Loads a given app specific lang
|
||||||
* @param lang_coed - the language code
|
* @param string $lang_code - the language code
|
||||||
* #param name - the name of the route
|
* @param string $name - the name of the app
|
||||||
*/
|
*/
|
||||||
public function route_lang($lang_code, $name) {
|
public function app_lang($lang_code, $name): void {
|
||||||
$dir = $GLOBALS['webroot'] . '/lang/' . $lang_code . '/routes/';
|
$dir = $GLOBALS['webroot'] . '/lang/' . $lang_code . '/apps/';
|
||||||
$file = $dir . $name . '.php';
|
$file = $dir . $name . '.php';
|
||||||
if (file_exists($file)) {
|
if (file_exists($file)) {
|
||||||
$lang = $GLOBALS['lang'];
|
$lang = $GLOBALS['lang'];
|
||||||
|
|
|
@ -1,123 +0,0 @@
|
||||||
<?php /* Copyright (c) 2024 Freya Murphy */
|
|
||||||
class MainModel {
|
|
||||||
|
|
||||||
// loaded route infomation
|
|
||||||
public $info;
|
|
||||||
public $db;
|
|
||||||
public $user_id;
|
|
||||||
|
|
||||||
private $users;
|
|
||||||
|
|
||||||
function __construct() {
|
|
||||||
$this->info = NULL;
|
|
||||||
$this->db = new DatabaseHelper();
|
|
||||||
$this->users = array();
|
|
||||||
$_SESSION['jwt'] = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJyb2xlIjoicmVzdF91c2VyIiwidXNlcl9pZCI6MSwiZXhwIjoxNzExODUxMDUzfQ.FUcFO44SWV--YtVOy7NftTF8OeeOYGZDaDHigygQxsY';
|
|
||||||
if (array_key_exists('jwt', $_SESSION)) {
|
|
||||||
$this->get_session($_SESSION['jwt']);
|
|
||||||
} else {
|
|
||||||
$this->user_id = NULL;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
private function get_session($jwt) {
|
|
||||||
$query = $this->db
|
|
||||||
->select("_api.verify_jwt('" . $jwt . "') AS user_id;");
|
|
||||||
$result = $query->row();
|
|
||||||
$user_id = $result['user_id'];
|
|
||||||
if ($user_id) {
|
|
||||||
$this->user_id = $user_id;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public function link_css($path) {
|
|
||||||
return '<link rel="stylesheet" href="/public/' . $path . '">';
|
|
||||||
}
|
|
||||||
|
|
||||||
public function link_js($path) {
|
|
||||||
return '<script src="/public/'. $path . '"></script>';
|
|
||||||
}
|
|
||||||
|
|
||||||
public function user() {
|
|
||||||
if ($this->user_id) {
|
|
||||||
return $this->db
|
|
||||||
->select('*')
|
|
||||||
->from('api.user')
|
|
||||||
->where('id')
|
|
||||||
->eq($this->user_id)
|
|
||||||
->row();
|
|
||||||
} else {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public function get_num($key, $default = NULL) {
|
|
||||||
if (!array_key_exists($key, $_GET)) {
|
|
||||||
if ($default !== NULL) {
|
|
||||||
return $default;
|
|
||||||
} else {
|
|
||||||
error_page(400, lang('error_400'));
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
$val = $_GET[$key];
|
|
||||||
$val = intval($val);
|
|
||||||
if ($val < 0) {
|
|
||||||
return 0;
|
|
||||||
} else {
|
|
||||||
return $val;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public function get_users($objs) {
|
|
||||||
$ids = array();
|
|
||||||
foreach ($objs as $obj) {
|
|
||||||
$id = $obj['user_id'];
|
|
||||||
if (!array_key_exists($id, $this->users)) {
|
|
||||||
array_push($ids, intval($id));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!empty($ids)) {
|
|
||||||
$result = $this->db
|
|
||||||
->select('*')
|
|
||||||
->from('api.user')
|
|
||||||
->where_in('id', $ids)
|
|
||||||
->rows();
|
|
||||||
foreach ($result as $user) {
|
|
||||||
$id = $user['id'];
|
|
||||||
$this->users[$id] = $user;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return $this->users;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function display_name($user) {
|
|
||||||
$name = '';
|
|
||||||
if ($user['first_name']) {
|
|
||||||
$name .= $user['first_name'];
|
|
||||||
}
|
|
||||||
if ($user['middle_name']) {
|
|
||||||
if ($name != '') {
|
|
||||||
$name .= ' ';
|
|
||||||
}
|
|
||||||
$name .= $user['middle_name'];
|
|
||||||
}
|
|
||||||
if ($user['last_name']) {
|
|
||||||
if ($name != '') {
|
|
||||||
$name .= ' ';
|
|
||||||
}
|
|
||||||
$name .= $user['last_name'];
|
|
||||||
}
|
|
||||||
if ($name == '') {
|
|
||||||
$name = '@' . $user['username'];
|
|
||||||
}
|
|
||||||
return $name;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function display_date($date) {
|
|
||||||
return $date;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
?>
|
|
|
@ -1,29 +0,0 @@
|
||||||
<?php /* Copyright (c) 2024 Freya Murphy */
|
|
||||||
abstract class Model {
|
|
||||||
// the main model
|
|
||||||
// shared by all controllers and models
|
|
||||||
public $main;
|
|
||||||
public $load;
|
|
||||||
|
|
||||||
// the database
|
|
||||||
public $db;
|
|
||||||
|
|
||||||
private $config;
|
|
||||||
|
|
||||||
function __construct() {
|
|
||||||
$this->main = $GLOBALS['__vars']['main'];
|
|
||||||
$this->load = $GLOBALS['__vars']['load'];
|
|
||||||
$this->db = $this->main->db;
|
|
||||||
$this->config = new Aesthetic();
|
|
||||||
}
|
|
||||||
|
|
||||||
public function get_data() {
|
|
||||||
$data = array();
|
|
||||||
$route = $this->main->info['route'];
|
|
||||||
$files = $this->config->get_files($route);
|
|
||||||
$data = array_merge($data, $files);
|
|
||||||
$data['self'] = $this->main->user();
|
|
||||||
return $data;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
?>
|
|
|
@ -1,127 +1,147 @@
|
||||||
<?php /* Copyright (c) 2024 Freya Murphy */
|
<?php /* Copyright (c) 2024 Freya Murphy */
|
||||||
class Router {
|
class Router {
|
||||||
|
|
||||||
private $main;
|
// the loader
|
||||||
private $load;
|
private $load;
|
||||||
private $routes;
|
|
||||||
|
|
||||||
function load_route($route) {
|
// the main model
|
||||||
$name = $route['name'];
|
private $main;
|
||||||
$controller_cls = $route['controller'];
|
|
||||||
$model_cls = $route['model'];
|
|
||||||
|
|
||||||
$root = $GLOBALS['webroot'];
|
/**
|
||||||
$dir = $root . '/routes/' . $name;
|
* Creates a router
|
||||||
require($dir . '/model.php');
|
* @param Loader $load - the main laoder object
|
||||||
require($dir . '/controller.php');
|
*/
|
||||||
|
function __construct($load) {
|
||||||
$model_ref = new ReflectionClass($model_cls);
|
|
||||||
$model = $model_ref->newInstance();
|
|
||||||
|
|
||||||
$controller_ref = new ReflectionClass($controller_cls);
|
|
||||||
$controller = $controller_ref->newInstance($model);
|
|
||||||
|
|
||||||
return $controller;
|
|
||||||
}
|
|
||||||
|
|
||||||
function __construct($main, $load) {
|
|
||||||
|
|
||||||
$routes = array(
|
|
||||||
'home' => array(
|
|
||||||
'slugs' => ['', 'home'],
|
|
||||||
'model' => 'HomeModel',
|
|
||||||
'controller' => 'HomeController',
|
|
||||||
),
|
|
||||||
);
|
|
||||||
|
|
||||||
$this->routes = array();
|
|
||||||
foreach ($routes as $name => $route) {
|
|
||||||
foreach ($route['slugs'] as $slug) {
|
|
||||||
$this->routes[$slug] = $route;
|
|
||||||
$this->routes[$slug]['name'] = $name;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->main = $main;
|
|
||||||
$this->load = $load;
|
$this->load = $load;
|
||||||
|
$this->main = $this->load->model('main');
|
||||||
}
|
}
|
||||||
|
|
||||||
function get_info() {
|
/**
|
||||||
$uri = parse_url($_SERVER['REQUEST_URI']);
|
* @param string $path - the current request path
|
||||||
|
* Gets the current route
|
||||||
|
* @return array<string,mixed>
|
||||||
|
*/
|
||||||
|
private function get_req_route($path): array {
|
||||||
|
// trim the path
|
||||||
|
$path = trim($path);
|
||||||
|
// remove first '/'
|
||||||
|
$path = substr($path, 1);
|
||||||
|
// get path parts
|
||||||
|
$parts = explode('/', $path);
|
||||||
|
|
||||||
|
$len = count($parts);
|
||||||
|
|
||||||
|
// get route info
|
||||||
|
$route = array();
|
||||||
|
// e.g. /
|
||||||
|
if ($path === '') {
|
||||||
|
$route = array(
|
||||||
|
'route' => '',
|
||||||
|
'slug' => 'index',
|
||||||
|
);
|
||||||
|
// e.g. /home /login
|
||||||
|
} else if ($len === 1) {
|
||||||
|
$route = array(
|
||||||
|
'route' => $parts[0],
|
||||||
|
'slug' => 'index',
|
||||||
|
);
|
||||||
|
// e.g. /home/posts
|
||||||
|
} else {
|
||||||
|
$route = array (
|
||||||
|
'route' => implode('/', array_slice($parts, 0, -1)),
|
||||||
|
'slug' => end($parts)
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
$route['app'] = $route['route'];
|
||||||
|
$routes = $GLOBALS['routes'];
|
||||||
|
if (array_key_exists($route['route'], $routes)) {
|
||||||
|
$route['route'] = $routes[$route['route']];
|
||||||
|
}
|
||||||
|
|
||||||
|
return $route;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the curret request info
|
||||||
|
* @return array<string,mixed>
|
||||||
|
*/
|
||||||
|
private function get_req(): array {
|
||||||
$method = $_SERVER['REQUEST_METHOD'];
|
$method = $_SERVER['REQUEST_METHOD'];
|
||||||
$parts = explode('/', $uri['path']);
|
|
||||||
|
|
||||||
$slug = sizeof($parts) > 1 ? $parts[1] : '';
|
$uri = parse_url($_SERVER['REQUEST_URI']);
|
||||||
$path = sizeof($parts) > 2 ? $parts[2] : 'index';
|
$path = $uri['path'];
|
||||||
|
|
||||||
if (sizeof($parts) > 3) {
|
return array_merge(
|
||||||
return NULL;
|
array(
|
||||||
}
|
'uri' => $uri,
|
||||||
|
'method' => $method,
|
||||||
return array(
|
'lang' => $this->get_lang(),
|
||||||
'method' => $method,
|
),
|
||||||
'uri' => $uri,
|
$this->get_req_route($path),
|
||||||
|
|
||||||
'slug' => $slug,
|
|
||||||
'path' => $path
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function handle_error($code) {
|
/**
|
||||||
$route = array(
|
* Gets the current language
|
||||||
'name' => 'error',
|
* @return string
|
||||||
'model' => 'ErrorModel',
|
*/
|
||||||
'controller' => 'ErrorController'
|
private function get_lang(): string {
|
||||||
);
|
return 'en_US';
|
||||||
$this->main->info = array(
|
}
|
||||||
'slug' => 'error',
|
|
||||||
'lang' => 'en_US',
|
/**
|
||||||
'route' => 'error'
|
* Handles a router error code
|
||||||
);
|
* @param int $code - the http error code
|
||||||
$controller = $this->load_route($route);
|
* @param bool $recursed
|
||||||
|
*/
|
||||||
|
private function handle_error($code, $recursed): void {
|
||||||
|
if ($recursed) {
|
||||||
|
die($code . ' (recursed)');
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->main->info['slug'] = 'index';
|
||||||
|
$this->main->info['app'] = 'error';
|
||||||
|
$this->main->info['route'] = 'apps/error';
|
||||||
|
$req = $this->main->info;
|
||||||
$_GET['code'] = $code;
|
$_GET['code'] = $code;
|
||||||
http_response_code($code);
|
|
||||||
$controller->index();
|
$this->handle_req($req, TRUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function handle_request() {
|
/**
|
||||||
$request = $this->get_info();
|
* @param array $req
|
||||||
|
* @param bool $recursed
|
||||||
|
*/
|
||||||
|
private function handle_req($req, $recursed = FALSE): void {
|
||||||
|
$controller = $this->load->controller($req['route']);
|
||||||
|
|
||||||
if ($request === NULL) {
|
if ($controller === NULL) {
|
||||||
$this->handle_error(404);
|
$this->handle_error(404, $recursed);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
$slug = $request['slug'];
|
|
||||||
if (!array_key_exists($slug, $this->routes)) {
|
|
||||||
$this->handle_error(404);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
$route = $this->routes[$slug];
|
|
||||||
$this->main->info = array(
|
|
||||||
'lang' => 'en_US',
|
|
||||||
'slug' => $slug,
|
|
||||||
'route' => $route['name'],
|
|
||||||
);
|
|
||||||
|
|
||||||
$controller = $this->load_route($route);
|
|
||||||
|
|
||||||
$path = $request['path'];
|
|
||||||
$ref = NULL;
|
$ref = NULL;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$ref = new ReflectionMethod($controller, $path);
|
$ref = new ReflectionMethod($controller, $req['slug']);
|
||||||
} catch (Exception $_e) {}
|
} catch (Exception $_e) {}
|
||||||
|
|
||||||
if ($ref === NULL || !$ref->isPublic()) {
|
if ($ref === NULL || !$ref->isPublic()) {
|
||||||
$this->handle_error(404);
|
$this->handle_error(404, $recursed);
|
||||||
return;
|
return;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$ref->invoke($controller);
|
$ref->invoke($controller);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handels the incomming reuqest
|
||||||
|
*/
|
||||||
|
public function handle_request(): void {
|
||||||
|
$req = $this->get_req();
|
||||||
|
$this->main->info = $req;
|
||||||
|
$this->handle_req($req);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
9
web/helper/error.php
Normal file
9
web/helper/error.php
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
<?php /* Copyright (c) 2024 Freya Murphy */
|
||||||
|
|
||||||
|
function error_page($code, $msg) {
|
||||||
|
$root = $GLOBALS['webroot'];
|
||||||
|
error_reporting(E_ERROR | E_PARSE);
|
||||||
|
http_response_code($code);
|
||||||
|
require($root . '/views/template/error.php');
|
||||||
|
die();
|
||||||
|
}
|
77
web/helper/lang.php
Normal file
77
web/helper/lang.php
Normal file
|
@ -0,0 +1,77 @@
|
||||||
|
<?php /* Copyright (c) 2024 Freya Murphy */
|
||||||
|
$lang = array();
|
||||||
|
|
||||||
|
function lang($key, $default = NULL, $sub = NULL) {
|
||||||
|
$lang = $GLOBALS['lang'];
|
||||||
|
if(array_key_exists($key, $lang)) {
|
||||||
|
if ($sub) {
|
||||||
|
return sprintf($lang[$key], ...$sub);
|
||||||
|
} else {
|
||||||
|
return $lang[$key];
|
||||||
|
}
|
||||||
|
} else if ($default !== NULL) {
|
||||||
|
return $default;
|
||||||
|
} else {
|
||||||
|
return $key;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function ilang($key,
|
||||||
|
$class = NULL,
|
||||||
|
$id = NULL,
|
||||||
|
$href = NULL,
|
||||||
|
$click = NULL,
|
||||||
|
$attrs = array(),
|
||||||
|
$sub = NULL,
|
||||||
|
$button = FALSE,
|
||||||
|
) {
|
||||||
|
$text = lang($key . "_text", FALSE, sub: $sub);
|
||||||
|
$tip = lang($key . "_tip", FALSE);
|
||||||
|
$icon = lang($key . "_icon", FALSE);
|
||||||
|
$content = lang($key . "_content", FALSE);
|
||||||
|
|
||||||
|
if ($click || $button) {
|
||||||
|
echo '<button ';
|
||||||
|
} else {
|
||||||
|
echo '<a ';
|
||||||
|
}
|
||||||
|
if ($tip) {
|
||||||
|
echo 'title="' . $tip . '" ';
|
||||||
|
echo 'aria-label="' . $tip . '" ';
|
||||||
|
}
|
||||||
|
if ($class) {
|
||||||
|
echo 'class="' . $class . '" ';
|
||||||
|
}
|
||||||
|
if ($id) {
|
||||||
|
echo 'id="' . $id . '" ';
|
||||||
|
}
|
||||||
|
if ($click) {
|
||||||
|
echo 'onclick="' . $click . '" ';
|
||||||
|
}
|
||||||
|
if ($href) {
|
||||||
|
echo 'href="' . $href . '" ';
|
||||||
|
}
|
||||||
|
foreach ($attrs as $key => $attr) {
|
||||||
|
echo $key . '="' . $attr . '" ';
|
||||||
|
}
|
||||||
|
echo '> ';
|
||||||
|
if ($icon) {
|
||||||
|
echo '<i class="' . $icon . '">';
|
||||||
|
if ($content) {
|
||||||
|
echo $content;
|
||||||
|
}
|
||||||
|
echo '</i>';
|
||||||
|
}
|
||||||
|
if ($text) {
|
||||||
|
echo '<span';
|
||||||
|
if ($icon) {
|
||||||
|
echo ' class="ml-sm"';
|
||||||
|
}
|
||||||
|
echo '>' . $text . '</span>';
|
||||||
|
}
|
||||||
|
if ($click) {
|
||||||
|
echo '</button>';
|
||||||
|
} else {
|
||||||
|
echo '</a>';
|
||||||
|
}
|
||||||
|
}
|
116
web/index.php
116
web/index.php
|
@ -2,114 +2,26 @@
|
||||||
|
|
||||||
session_start();
|
session_start();
|
||||||
|
|
||||||
$lang = array();
|
|
||||||
$__vars = array();
|
|
||||||
$webroot = dirname(__FILE__);
|
$webroot = dirname(__FILE__);
|
||||||
|
|
||||||
function error_page($code, $msg) {
|
// load all the helper files
|
||||||
$root = $GLOBALS['webroot'];
|
require($webroot . '/helper/error.php');
|
||||||
error_reporting(E_ERROR | E_PARSE);
|
require($webroot . '/helper/lang.php');
|
||||||
http_response_code($code);
|
|
||||||
require($root . '/core/error.php');
|
|
||||||
die();
|
|
||||||
}
|
|
||||||
|
|
||||||
function lang($key, $default = NULL, $sub = NULL) {
|
// load all the config files
|
||||||
$lang = $GLOBALS['lang'];
|
require($webroot . '/config/aesthetic.php');
|
||||||
if(array_key_exists($key, $lang)) {
|
require($webroot . '/config/routes.php');
|
||||||
if ($sub) {
|
|
||||||
return sprintf($lang[$key], ...$sub);
|
|
||||||
} else {
|
|
||||||
return $lang[$key];
|
|
||||||
}
|
|
||||||
} else if ($default !== NULL) {
|
|
||||||
return $default;
|
|
||||||
} else {
|
|
||||||
return $key;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function ilang($key,
|
// load all core files
|
||||||
$class = NULL,
|
require($webroot . '/core/_controller.php');
|
||||||
$id = NULL,
|
require($webroot . '/core/_model.php');
|
||||||
$href = NULL,
|
require($webroot . '/core/database.php');
|
||||||
$click = NULL,
|
require($webroot . '/core/loader.php');
|
||||||
$attrs = array(),
|
require($webroot . '/core/router.php');
|
||||||
$sub = NULL,
|
|
||||||
$button = FALSE,
|
|
||||||
) {
|
|
||||||
$text = lang($key . "_text", FALSE, sub: $sub);
|
|
||||||
$tip = lang($key . "_tip", FALSE);
|
|
||||||
$icon = lang($key . "_icon", FALSE);
|
|
||||||
$content = lang($key . "_content", FALSE);
|
|
||||||
|
|
||||||
if ($click || $button) {
|
|
||||||
echo '<button ';
|
|
||||||
} else {
|
|
||||||
echo '<a ';
|
|
||||||
}
|
|
||||||
if ($tip) {
|
|
||||||
echo 'title="' . $tip . '" ';
|
|
||||||
echo 'aria-label="' . $tip . '" ';
|
|
||||||
}
|
|
||||||
if ($class) {
|
|
||||||
echo 'class="' . $class . '" ';
|
|
||||||
}
|
|
||||||
if ($id) {
|
|
||||||
echo 'id="' . $id . '" ';
|
|
||||||
}
|
|
||||||
if ($click) {
|
|
||||||
echo 'onclick="' . $click . '" ';
|
|
||||||
}
|
|
||||||
if ($href) {
|
|
||||||
echo 'href="' . $href . '" ';
|
|
||||||
}
|
|
||||||
foreach ($attrs as $key => $attr) {
|
|
||||||
echo $key . '="' . $attr . '" ';
|
|
||||||
}
|
|
||||||
echo '> ';
|
|
||||||
if ($icon) {
|
|
||||||
echo '<i class="' . $icon . '">';
|
|
||||||
if ($content) {
|
|
||||||
echo $content;
|
|
||||||
}
|
|
||||||
echo '</i>';
|
|
||||||
}
|
|
||||||
if ($text) {
|
|
||||||
echo '<span';
|
|
||||||
if ($icon) {
|
|
||||||
echo ' class="ml-sm"';
|
|
||||||
}
|
|
||||||
echo '>' . $text . '</span>';
|
|
||||||
}
|
|
||||||
if ($click) {
|
|
||||||
echo '</button>';
|
|
||||||
} else {
|
|
||||||
echo '</a>';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function __init() {
|
function __init() {
|
||||||
|
|
||||||
$root = $GLOBALS['webroot'];
|
|
||||||
|
|
||||||
// load all core files
|
|
||||||
require($root . '/core/database.php');
|
|
||||||
require($root . '/core/aesthetic.php');
|
|
||||||
require($root . '/core/controller.php');
|
|
||||||
require($root . '/core/model.php');
|
|
||||||
require($root . '/core/loader.php');
|
|
||||||
require($root . '/core/main.php');
|
|
||||||
require($root . '/core/router.php');
|
|
||||||
|
|
||||||
$main = new MainModel();
|
|
||||||
$load = new Loader();
|
$load = new Loader();
|
||||||
$router = new Router($main, $load);
|
$router = new Router($load);
|
||||||
|
|
||||||
$GLOBALS['__vars']['main'] = $main;
|
|
||||||
$GLOBALS['__vars']['load'] = $load;
|
|
||||||
$GLOBALS['__vars']['router'] = $router;
|
|
||||||
|
|
||||||
$router->handle_request();
|
$router->handle_request();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -118,5 +30,3 @@ if (!file_exists('/status/ready')) {
|
||||||
}
|
}
|
||||||
|
|
||||||
__init();
|
__init();
|
||||||
|
|
||||||
?>
|
|
||||||
|
|
26
web/lang/en_US/api_lang.php
Normal file
26
web/lang/en_US/api_lang.php
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
<?php /* Copyright (c) 2024 Freya Murphy */
|
||||||
|
|
||||||
|
// user column
|
||||||
|
$lang['api_column_username'] = 'username';
|
||||||
|
$lang['api_column_first_name'] = 'first name';
|
||||||
|
$lang['api_column_last_name'] = 'last name';
|
||||||
|
$lang['api_column_middle_name'] = 'middle name';
|
||||||
|
$lang['api_column_email'] = 'email';
|
||||||
|
$lang['api_column_gender'] = 'gender';
|
||||||
|
$lang['api_column_join_date'] = 'join date';
|
||||||
|
$lang['api_column_birth_date'] = 'birth date';
|
||||||
|
$lang['api_column_profile_avatar'] = 'avatar image';
|
||||||
|
$lang['api_column_profile_banner'] = 'banner image';
|
||||||
|
$lang['api_column_profile_bio'] = 'profile bio';
|
||||||
|
|
||||||
|
// post column
|
||||||
|
$lang['api_column_content'] = 'post content';
|
||||||
|
|
||||||
|
// error messages
|
||||||
|
$lang['api_denied'] = 'Action was denied';
|
||||||
|
$lang['api_null_value'] = '%s cannot be empty';
|
||||||
|
$lang['api_unique_value'] = '%s is not available (not unique)';
|
||||||
|
$lang['api_min_value'] = '%s length cannot be less than %s';
|
||||||
|
$lang['api_max_value'] = '%s length cannot exceed %s';
|
||||||
|
|
||||||
|
?>
|
9
web/lang/en_US/apps/home.php
Normal file
9
web/lang/en_US/apps/home.php
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
$lang['title'] = 'Home';
|
||||||
|
|
||||||
|
// actions
|
||||||
|
$lang['action_load_posts_text'] = 'Load more posts';
|
||||||
|
$lang['action_load_posts_tip'] = 'Load more posts';
|
||||||
|
|
||||||
|
?>
|
|
@ -1,4 +1,4 @@
|
||||||
<?php
|
<?php /* Copyright (c) 2024 Freya Murphy */
|
||||||
|
|
||||||
// Navigation Bar Lang
|
// Navigation Bar Lang
|
||||||
$lang['action_home_text'] = 'Home';
|
$lang['action_home_text'] = 'Home';
|
||||||
|
@ -29,6 +29,10 @@ $lang['action_load_comments_tip'] = 'Load more comments';
|
||||||
// General
|
// General
|
||||||
$lang['action_submit_text'] = 'Submit';
|
$lang['action_submit_text'] = 'Submit';
|
||||||
$lang['action_submit_tip'] = 'Submit';
|
$lang['action_submit_tip'] = 'Submit';
|
||||||
|
$lang['action_close_text'] = '';
|
||||||
|
$lang['action_close_tip'] = 'Close';
|
||||||
|
$lang['action_close_icon'] = 'mi mi-sm';
|
||||||
|
$lang['action_close_content'] = 'close';
|
||||||
|
|
||||||
// Modals
|
// Modals
|
||||||
$lang['action_modal_close_text'] = '';
|
$lang['action_modal_close_text'] = '';
|
||||||
|
@ -36,6 +40,10 @@ $lang['action_modal_close_tip'] = 'Close modal.';
|
||||||
$lang['action_modal_close_icon'] = 'mi mi-sm';
|
$lang['action_modal_close_icon'] = 'mi mi-sm';
|
||||||
$lang['action_modal_close_content'] = 'close';
|
$lang['action_modal_close_content'] = 'close';
|
||||||
|
|
||||||
|
$lang['new_post_modal_title'] = 'Author New Post';
|
||||||
|
$lang['action_new_post_text'] = 'What\'s on your mind, %s';
|
||||||
|
$lang['action_new_post_tip'] = 'Author a new post.';
|
||||||
|
|
||||||
// Words
|
// Words
|
||||||
$lang['now'] = 'Now';
|
$lang['now'] = 'Now';
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
<?php
|
<?php /* Copyright (c) 2024 Freya Murphy */
|
||||||
|
|
||||||
$lang['error_400'] = 'Bad request';
|
$lang['error_400'] = 'Bad request';
|
||||||
$lang['error_404'] = 'Resource not found';
|
$lang['error_404'] = 'Resource not found';
|
||||||
|
|
|
@ -1,14 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
$lang['title'] = 'Home';
|
|
||||||
|
|
||||||
// actions
|
|
||||||
$lang['action_new_post_text'] = 'What\'s on your mind, %s';
|
|
||||||
$lang['action_new_post_tip'] = 'Author a new post.';
|
|
||||||
$lang['action_load_posts_text'] = 'Load more posts';
|
|
||||||
$lang['action_load_posts_tip'] = 'Load more posts';
|
|
||||||
|
|
||||||
// modals
|
|
||||||
$lang['new_post_modal_title'] = 'Author New Post';
|
|
||||||
|
|
||||||
?>
|
|
|
@ -52,6 +52,8 @@ body {
|
||||||
}
|
}
|
||||||
|
|
||||||
header {
|
header {
|
||||||
|
top: 0;
|
||||||
|
position: sticky;
|
||||||
height: 3.5rem;
|
height: 3.5rem;
|
||||||
background-color: var(--primary);
|
background-color: var(--primary);
|
||||||
display: flex;
|
display: flex;
|
||||||
|
@ -145,6 +147,10 @@ input:focus {
|
||||||
align-items: center;
|
align-items: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.nav {
|
||||||
|
position: sticky;
|
||||||
|
}
|
||||||
|
|
||||||
.nav-right {
|
.nav-right {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
justify-content: flex-end;
|
justify-content: flex-end;
|
||||||
|
@ -333,6 +339,30 @@ input:focus {
|
||||||
border-radius: .5rem;
|
border-radius: .5rem;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
animation: fadeIn .1s, slideInModal .1s linear;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes slideInModal {
|
||||||
|
0% {
|
||||||
|
animation-timing-function: ease-in;
|
||||||
|
transform: translate(-50%, -60%);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes slideIn {
|
||||||
|
0% {
|
||||||
|
animation-timing-function: ease-out;
|
||||||
|
transform: translate(0, -50%);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes fadeIn {
|
||||||
|
0% {
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.modal>form {
|
.modal>form {
|
||||||
|
@ -402,3 +432,30 @@ button[type="submit"]:hover {
|
||||||
background-color: var(--logo);
|
background-color: var(--logo);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#toast-container {
|
||||||
|
position: fixed;
|
||||||
|
top: 4rem;
|
||||||
|
left: 100%;
|
||||||
|
transform: translateX(-110%);
|
||||||
|
margin-top: 1rem;
|
||||||
|
z-index: 10000;
|
||||||
|
}
|
||||||
|
|
||||||
|
.toast {
|
||||||
|
padding: .75rem;
|
||||||
|
margin: .5rem;
|
||||||
|
border-radius: .5rem;
|
||||||
|
min-width: 15rem;
|
||||||
|
font-family: sfpro;
|
||||||
|
animation: fadeIn .1s, slideIn .25s linear;
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
}
|
||||||
|
|
||||||
|
.toast.error {
|
||||||
|
background-color: var(--error);
|
||||||
|
}
|
||||||
|
|
||||||
|
.toast.success {
|
||||||
|
background-color: var(--success);
|
||||||
|
}
|
||||||
|
|
|
@ -1,4 +1,8 @@
|
||||||
|
|
||||||
|
///
|
||||||
|
/// document ready functions
|
||||||
|
///
|
||||||
|
|
||||||
let ready = false;
|
let ready = false;
|
||||||
|
|
||||||
$(function() {
|
$(function() {
|
||||||
|
@ -15,9 +19,14 @@ var r$ = function(callback) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function observe(containerSelector, elementSelector, callback) {
|
///
|
||||||
r$(() => {
|
/// dom observer
|
||||||
|
/// checks for elements on the DOM now and added later
|
||||||
|
///
|
||||||
|
|
||||||
|
function observe(containerSelector, elementSelector, callback) {
|
||||||
|
|
||||||
|
r$(() => {
|
||||||
$(containerSelector + ' ' + elementSelector).each(function (_, e) {
|
$(containerSelector + ' ' + elementSelector).each(function (_, e) {
|
||||||
let me = $(e);
|
let me = $(e);
|
||||||
callback(me);
|
callback(me);
|
||||||
|
@ -37,9 +46,64 @@ function observe(containerSelector, elementSelector, callback) {
|
||||||
};
|
};
|
||||||
|
|
||||||
var target = $(containerSelector)[0];
|
var target = $(containerSelector)[0];
|
||||||
|
|
||||||
|
if (!target) {
|
||||||
|
console.warn('[observe] didnt find container: ', containerSelector);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
var config = { childList: true, subtree: true };
|
var config = { childList: true, subtree: true };
|
||||||
var MutationObserver = window.MutationObserver;
|
var MutationObserver = window.MutationObserver;
|
||||||
var observer = new MutationObserver(onMutationsObserved);
|
var observer = new MutationObserver(onMutationsObserved);
|
||||||
observer.observe(target, config);
|
observer.observe(target, config);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// ajax setup
|
||||||
|
///
|
||||||
|
|
||||||
|
let ajaxHeaders = {};
|
||||||
|
ajaxHeaders['Content-Type'] = 'application/json';
|
||||||
|
if (jwtStr) {
|
||||||
|
ajaxHeaders['Authorization'] = 'Bearer ' + jwtStr
|
||||||
|
}
|
||||||
|
|
||||||
|
$.ajaxSetup({
|
||||||
|
headers: ajaxHeaders
|
||||||
|
})
|
||||||
|
|
||||||
|
///
|
||||||
|
/// ajax error handle
|
||||||
|
///
|
||||||
|
|
||||||
|
var errorToast = (xhr) => {
|
||||||
|
let data = xhr.responseJSON;
|
||||||
|
let msg = data.message;
|
||||||
|
let detail = data.details;
|
||||||
|
let hint = data.hint;
|
||||||
|
|
||||||
|
let query = '?msg=' + msg;
|
||||||
|
if (detail) {
|
||||||
|
query += '&detail=' + detail;
|
||||||
|
}
|
||||||
|
if (hint) {
|
||||||
|
query += '&hint=' + hint;
|
||||||
|
}
|
||||||
|
let url = '/template/toast' + query;
|
||||||
|
$.get(url, function (data) {
|
||||||
|
$('#toast-container').prepend(data);
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
observe('#toast-container', '.action-close-toast', function(el) {
|
||||||
|
el.on('click', function() {
|
||||||
|
el.parent().remove();
|
||||||
|
});
|
||||||
|
|
||||||
|
setTimeout(function() {
|
||||||
|
el.parent().remove();
|
||||||
|
}, 5000);
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
observe('.post', '.action-load-comments', function(me) {
|
observe('#main-content', '.action-load-comments', function(me) {
|
||||||
me.on('click', function() {
|
me.on('click', function() {
|
||||||
let page = me.attr('page');
|
let page = me.attr('page');
|
||||||
if (!page) {
|
if (!page) {
|
|
@ -1,20 +0,0 @@
|
||||||
<?php /* Copyright (c) 2024 Freya Murphy */
|
|
||||||
class ErrorController extends Controller {
|
|
||||||
|
|
||||||
private $model;
|
|
||||||
|
|
||||||
function __construct($model) {
|
|
||||||
parent::__construct();
|
|
||||||
$this->model = $model;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function index() {
|
|
||||||
parent::index();
|
|
||||||
$data = $this->model->get_data();
|
|
||||||
$this->view('header', $data);
|
|
||||||
$this->app_view('error', $data);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
?>
|
|
|
@ -1,4 +0,0 @@
|
||||||
<div id="error">
|
|
||||||
<h1><?=$title?></h1>
|
|
||||||
<span><?=$msg?></span>
|
|
||||||
</div>
|
|
6
web/views/apps/error/main.php
Normal file
6
web/views/apps/error/main.php
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
<?php /* Copyright (c) 2024 Freya Murphy */ ?>
|
||||||
|
<?php /* vi: syntax=php */ ?>
|
||||||
|
<div id="error">
|
||||||
|
<h1><?=$title?></h1>
|
||||||
|
<span><?=$msg?></span>
|
||||||
|
</div>
|
|
@ -1,4 +1,5 @@
|
||||||
<?php // vi: syntax=php ?>
|
<?php /* Copyright (c) 2024 Freya Murphy */ ?>
|
||||||
|
<?php /* vi: syntax=php */ ?>
|
||||||
<div id="main-content">
|
<div id="main-content">
|
||||||
<?php if ($self): ?>
|
<?php if ($self): ?>
|
||||||
<div id="new-post" class="card">
|
<div id="new-post" class="card">
|
||||||
|
@ -15,7 +16,7 @@
|
||||||
</div>
|
</div>
|
||||||
<script>
|
<script>
|
||||||
$('#action-new-post').on('click', function() {
|
$('#action-new-post').on('click', function() {
|
||||||
$.get( "/home/new_post_modal", function (data) {
|
$.get( "/modal/new_post", function (data) {
|
||||||
$(document.body).append(data);
|
$(document.body).append(data);
|
||||||
});
|
});
|
||||||
})
|
})
|
|
@ -1,2 +1,4 @@
|
||||||
|
<?php /* Copyright (c) 2024 Freya Murphy */ ?>
|
||||||
|
<?php /* vi: syntax=php */ ?>
|
||||||
<body>
|
<body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
@ -1,10 +1,18 @@
|
||||||
<?php // vi: syntax=php ?>
|
<?php /* Copyright (c) 2024 Freya Murphy */ ?>
|
||||||
|
<?php /* vi: syntax=php */ ?>
|
||||||
<?php
|
<?php
|
||||||
$self = $this->main->user();
|
$self = $this->main->user();
|
||||||
?>
|
?>
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
|
<script>
|
||||||
|
<?php if ($this->main->session): ?>
|
||||||
|
var jwtStr = <?=json_encode($this->main->session['jwt'])?>;
|
||||||
|
<?php else: ?>
|
||||||
|
var jwtStr = null;
|
||||||
|
<?php endif; ?>
|
||||||
|
</script>
|
||||||
<?php
|
<?php
|
||||||
foreach ($js_files as $js) {
|
foreach ($js_files as $js) {
|
||||||
echo $this->main->link_js($js);
|
echo $this->main->link_js($js);
|
||||||
|
@ -71,4 +79,6 @@
|
||||||
menu.toggleClass('visible');
|
menu.toggleClass('visible');
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
</header>
|
</header>
|
||||||
|
<div id="toast-container">
|
||||||
|
</div>
|
||||||
|
|
|
@ -1,7 +1,9 @@
|
||||||
|
<?php /* Copyright (c) 2024 Freya Murphy */ ?>
|
||||||
|
<?php /* vi: syntax=php */ ?>
|
||||||
<?php
|
<?php
|
||||||
$user = $this->main->user();
|
$user = $this->main->user();
|
||||||
?>
|
?>
|
||||||
<form>
|
<form id="new-post-form">
|
||||||
<div class="modal-content new-post-modal">
|
<div class="modal-content new-post-modal">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<?php $this->view('template/pfp', array('user' => $user))?>
|
<?php $this->view('template/pfp', array('user' => $user))?>
|
||||||
|
@ -12,8 +14,8 @@
|
||||||
</div>
|
</div>
|
||||||
<textarea
|
<textarea
|
||||||
type="text"
|
type="text"
|
||||||
name="text"
|
name="content"
|
||||||
id="text"
|
id="new-post-content"
|
||||||
placeholder="<?=lang('action_new_post_text', sub: [$user['first_name']])?>"
|
placeholder="<?=lang('action_new_post_text', sub: [$user['first_name']])?>"
|
||||||
></textarea>
|
></textarea>
|
||||||
</div>
|
</div>
|
||||||
|
@ -26,3 +28,19 @@
|
||||||
)?>
|
)?>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
<script>
|
||||||
|
$('#new-post-form').submit(function(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
let content = $('#new-post-content').val();
|
||||||
|
|
||||||
|
$.ajax({
|
||||||
|
url: '/api/post',
|
||||||
|
method: 'POST',
|
||||||
|
data: JSON.stringify({ content }),
|
||||||
|
success: function(data) {
|
||||||
|
window.location.reload();
|
||||||
|
},
|
||||||
|
error: errorToast
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script>
|
|
@ -1,3 +1,5 @@
|
||||||
|
<?php /* Copyright (c) 2024 Freya Murphy */ ?>
|
||||||
|
<?php /* vi: syntax=php */ ?>
|
||||||
<div class="comment row mt">
|
<div class="comment row mt">
|
||||||
<?php $this->view('template/pfp', array('user' => $user))?>
|
<?php $this->view('template/pfp', array('user' => $user))?>
|
||||||
<div class="ml col sub-card">
|
<div class="ml col sub-card">
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
<?php /* Copyright (c) 2024 Freya Murphy */ ?>
|
||||||
|
<?php /* vi: syntax=php */ ?>
|
||||||
<div class="modal-container">
|
<div class="modal-container">
|
||||||
<div class="modal">
|
<div class="modal">
|
||||||
<div class="modal-header row">
|
<div class="modal-header row">
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
<?php /* Copyright (c) 2024 Freya Murphy */ ?>
|
||||||
|
<?php /* vi: syntax=php */ ?>
|
||||||
<?php
|
<?php
|
||||||
$class = isset($class) ? $class : '';
|
$class = isset($class) ? $class : '';
|
||||||
?>
|
?>
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
<?php /* Copyright (c) 2024 Freya Murphy */ ?>
|
||||||
|
<?php /* vi: syntax=php */ ?>
|
||||||
<div class="post card">
|
<div class="post card">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<?php $this->view('template/pfp', array('user' => $user))?>
|
<?php $this->view('template/pfp', array('user' => $user))?>
|
||||||
|
|
19
web/views/template/toast.php
Normal file
19
web/views/template/toast.php
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
<?php /* Copyright (c) 2024 Freya Murphy */ ?>
|
||||||
|
<?php /* vi: syntax=php */ ?>
|
||||||
|
<?php
|
||||||
|
$params = array();
|
||||||
|
|
||||||
|
if ($detail) {
|
||||||
|
array_push($params, lang('api_column_' . $detail));
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($hint) {
|
||||||
|
array_push($params, $hint);
|
||||||
|
}
|
||||||
|
|
||||||
|
$msg = lang($msg, sub: $params);
|
||||||
|
?>
|
||||||
|
<div class="toast error">
|
||||||
|
<?=ucfirst($msg)?>
|
||||||
|
<?=ilang('action_close', class: 'action-close-toast')?>
|
||||||
|
</div>
|
Loading…
Reference in a new issue