mirror of
https://codeberg.org/vlw/vlw.se.git
synced 2025-09-14 05:13:46 +02:00
Compare commits
No commits in common. "f961579c79884292b50295ae55033720d65d0371" and "28bb00400453099b8c4727f2315c4867c84e0328" have entirely different histories.
f961579c79
...
28bb004004
15 changed files with 645 additions and 59 deletions
4
.gitignore
vendored
4
.gitignore
vendored
|
@ -1,7 +1,9 @@
|
|||
# Public assets #
|
||||
#################
|
||||
public/robots.txt
|
||||
public/.well-known
|
||||
public/assets/js/modules/npm
|
||||
|
||||
assets/js/modules/npm
|
||||
|
||||
# Bootstrapping #
|
||||
#################
|
||||
|
|
103
README.md
103
README.md
|
@ -1,66 +1,73 @@
|
|||
# vlw.se
|
||||
This is the source code behind [vlw.se](https://vlw.se) which is my personal website that I have written and designed from the ground up. The website is built on top of my own [web framework](https://vegvisir.vlw.se) and its API is also built on top of my own [API framework](https://reflect.vlw.se).
|
||||
This is the source code behind [vlw.se](https://vlw.se) which has been written from the ground up by me. This website is built on top of my [Vegvisir web framework](https://vegvisir.vlw.se) and my [Reflect API framework](https://reflect.vlw.se).
|
||||
|
||||
# Installation
|
||||
Here's how you get my website up and running on your own machine. Note, I have only tested this on Linux and the install script we will run later is written in bash.
|
||||
If you for whatever reason want to get this website up and running for yourself this is how that is done.
|
||||
|
||||
**Make sure you have both of these package managers installed before proceeding:**
|
||||
- [Composer](https://getcomposer.org/)
|
||||
- [NPM](https://www.npmjs.com/)
|
||||
## This website requires the following prerequisites
|
||||
- [PHP 8.0+](https://www.php.net/)
|
||||
- [MariaDB 14+](https://mariadb.org/)
|
||||
- [The NPM package manager](https://www.npmjs.com/)
|
||||
- [The Reflect API framework](https://reflect.vlw.se)
|
||||
- [The Vegvisir web framework](https://vegvisir.vlw.se)
|
||||
- [The composer package manager](https://getcomposer.org/)
|
||||
|
||||
## 1. Clone this repo
|
||||
Clone/download this repo to your machine. Preferably to a non-public directory - the frameworks will handle that.
|
||||
**Confimed supported framework versions:**
|
||||
Vegvisir|Reflect
|
||||
--|--
|
||||
✅ [`3.1.0`](https://codeberg.org/vegvisir/vegvisir/releases/tag/3.1.0)|✅ [`2.7.2`](https://codeberg.org/reflect/reflect/releases/tag/2.7.2)
|
||||
|
||||
```
|
||||
git clone https://codeberg.org/vlw/vlw.se --depth 1
|
||||
```
|
||||
## Website (Vegvisir)
|
||||
1. **Download this repo**
|
||||
|
||||
## 2. Install [Vegvisir](https://vegvisir.vlw.se) and [Reflect](https://reflect.vlw.se)
|
||||
Follow the installation instructions for my web, and API framework. This site uses the default configuration for both frameworks so the only thing you need to do after you've installed both is to point the `root_path` and `endpoints` directory respectively to the directory where you cloned this repo.
|
||||
Git clone or download this repo to any local folder
|
||||
```
|
||||
git clone https://codeberg.org/vlw/vlw.se
|
||||
```
|
||||
2. **Download and install Vegvisir**
|
||||
|
||||
- [Vegvisir installation](https://vegvisir.vlw.se)
|
||||
- [Reflect installation](https://reflect.vlw.se)
|
||||
Follow the installation instructions for [Vegvisir](https://vegvisir.vlw.se/docs/installation) and point the `root_path` variable to your local vlw.se folder.
|
||||
|
||||
*Example:*
|
||||
```sh
|
||||
# Vegvisir
|
||||
root_path = "/var/www/vlw.se"
|
||||
# Reflect
|
||||
endpoints = "/var/www/vlw.se"
|
||||
```
|
||||
3. **Run the install script**
|
||||
|
||||
## 3. Run the install script
|
||||
Run the `install.sh` script from the root of the repo directory. [Make sure you have the required package managers installed](#installation).
|
||||
This bash script will install dependencies and make npm modules public.
|
||||
```
|
||||
./install.sh
|
||||
```
|
||||
|
||||
**Example:**
|
||||
```sh
|
||||
# vlw@example:$
|
||||
cd /var/www/vlw.se
|
||||
# vlw@example:/var/www/vlw.se$
|
||||
./install.sh
|
||||
```
|
||||
Et voila! You probably want to install the API-side too but the website itself should now be accessible from your configured Vegvisir host.
|
||||
|
||||
## 4. Import the database templates
|
||||
There's are two SQL files that you can download from the releases page that has a snapshot of the MariaDB databases I use on my live website. The snapshot data for the website databse is not guaranteed to be up to date; but the database structure will be. Download and import these files into two existing databases. One for the website data, and the other has the Reflect API configurations.
|
||||
## API (Reflect)
|
||||
The API (and database) is where most content is stored and served from on this website.
|
||||
|
||||
- [Download SQL-snapshots](https://codeberg.org/vlw/vlw.se/releases)
|
||||
1. **Download this repo**
|
||||
|
||||
## 5. Set environment variables
|
||||
Make a copy of the `.env.example.ini` file called `.env.ini` from the root directory of the repo. There are a few parameters you can change here but the required ones are the following:
|
||||
**You can skip this if you've already downloaded the repo from step 1 in the website installation.**
|
||||
|
||||
```ini
|
||||
[client_api]
|
||||
base_url = ""
|
||||
api_key = ""
|
||||
Otherwise... Git clone or download this repo to any local folder
|
||||
```
|
||||
git clone https://codeberg.org/vlw/vlw.se
|
||||
```
|
||||
|
||||
[server_database]
|
||||
host = ""
|
||||
user = ""
|
||||
pass = ""
|
||||
db = ""
|
||||
```
|
||||
2. **Download and install Reflect**
|
||||
|
||||
Please refer to the comments in the ini file for more information about each field.
|
||||
Follow the installation instructions for [Reflect](https://reflect.vlw.se/docs/installation) and point the `endpoints` variable to the `/api` subdirectory in the local vlw.se folder.
|
||||
|
||||
## Done!
|
||||
That should be it. Navigate to your configured Vegvisir public host!
|
||||
3. **Install dependencies**
|
||||
|
||||
`cd` into the api folder and install dependencies with composer.
|
||||
```
|
||||
composer install --optimize-autoloader
|
||||
```
|
||||
|
||||
4. **Create and import database**
|
||||
|
||||
[Create and] import the two databases associated with vlw.se data and the Reflect API configurations from `.sql` files on the Releases page.
|
||||
|
||||
5. **Set environment variables**
|
||||
|
||||
Make a copy of `/api/.env.example.ini` and change the `[vlwdb]` variables with your MariaDB credentials.
|
||||
|
||||
6. **Set environment variables for website**
|
||||
|
||||
It's reasonable to assume if you've installed the website from this repo that you'd also want to use the API with it. Start my making a copy of `/.env.example.ini` (root directory) and change the `[api]` variables to point to your API hostname.
|
||||
|
|
|
@ -29,7 +29,7 @@
|
|||
|
||||
(new Rules(SearchTable::ID->value))
|
||||
->type(Type::STRING)
|
||||
->min(1)
|
||||
->min(10)
|
||||
->max(10)
|
||||
->default(null),
|
||||
|
||||
|
|
60
endpoints/work/DELETE.php
Normal file
60
endpoints/work/DELETE.php
Normal file
|
@ -0,0 +1,60 @@
|
|||
<?php
|
||||
|
||||
use Reflect\{Response, Path};
|
||||
use ReflectRules\{Ruleset, Rules, Type};
|
||||
|
||||
use const VLW\API\RESP_DELETE_OK;
|
||||
use VLW\Database\Database;
|
||||
use VLW\Database\Tables\Work\WorkTable;
|
||||
|
||||
require_once Path::root("src/Endpoints.php");
|
||||
require_once Path::root("src/Database/Database.php");
|
||||
require_once Path::root("src/Database/Tables/Work.php");
|
||||
|
||||
class DELETE_Work extends Database {
|
||||
protected Ruleset $ruleset;
|
||||
|
||||
public function __construct() {
|
||||
$this->ruleset = new Ruleset(strict: true);
|
||||
|
||||
$this->ruleset->POST([
|
||||
(new Rules(WorkTable::ID->value))
|
||||
->type(Type::STRING)
|
||||
->min(1)
|
||||
->max(parent::SIZE_VARCHAR),
|
||||
|
||||
(new Rules(WorkTable::TITLE->value))
|
||||
->type(Type::STRING)
|
||||
->min(3)
|
||||
->max(parent::SIZE_VARCHAR),
|
||||
|
||||
(new Rules(WorkTable::SUMMARY->value))
|
||||
->type(Type::STRING)
|
||||
->min(1)
|
||||
->max(parent::SIZE_TEXT),
|
||||
|
||||
(new Rules(WorkTable::IS_LISTED->value))
|
||||
->type(Type::BOOLEAN),
|
||||
|
||||
(new Rules(WorkTable::DATE_MODIFIED->value))
|
||||
->type(Type::NUMBER)
|
||||
->min(1)
|
||||
->max(parent::SIZE_UINT8),
|
||||
|
||||
(new Rules(WorkTable::DATE_CREATED->value))
|
||||
->type(Type::NUMBER)
|
||||
->min(1)
|
||||
->max(parent::SIZE_UINT8)
|
||||
]);
|
||||
|
||||
$this->ruleset->validate_or_exit();
|
||||
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
public function main(): Response {
|
||||
return $this->db->for(FieldsEnumsModel::NAME)->delete($_POST) === true
|
||||
? new Response(RESP_DELETE_OK)
|
||||
: new Response("Failed to delete work entity", 500);
|
||||
}
|
||||
}
|
109
endpoints/work/PATCH.php
Normal file
109
endpoints/work/PATCH.php
Normal file
|
@ -0,0 +1,109 @@
|
|||
<?php
|
||||
|
||||
use Reflect\Call;
|
||||
use Reflect\{Response, Path};
|
||||
use ReflectRules\{Ruleset, Rules, Type};
|
||||
|
||||
use VLW\API\Endpoints;
|
||||
use VLW\Database\Database;
|
||||
use VLW\Database\Tables\Work\{
|
||||
WorkTable,
|
||||
PermalinksTable
|
||||
};
|
||||
|
||||
require_once Path::root("src/Endpoints.php");
|
||||
require_once Path::root("src/Database/Database.php");
|
||||
require_once Path::root("src/Database/Tables/Work/Work.php");
|
||||
require_once Path::root("src/Database/Tables/Work/WorkPermalinks.php");
|
||||
|
||||
class PATCH_Work extends Database {
|
||||
protected Ruleset $ruleset;
|
||||
|
||||
public function __construct() {
|
||||
$this->ruleset = new Ruleset(strict: true);
|
||||
|
||||
$this->ruleset->GET([
|
||||
(new Rules(WorkTable::ID->value))
|
||||
->required()
|
||||
->type(Type::STRING)
|
||||
->min(1)
|
||||
->max(parent::SIZE_VARCHAR)
|
||||
]);
|
||||
|
||||
$this->ruleset->POST([
|
||||
(new Rules(WorkTable::TITLE->value))
|
||||
->type(Type::STRING)
|
||||
->min(3)
|
||||
->max(parent::SIZE_VARCHAR),
|
||||
|
||||
(new Rules(WorkTable::SUMMARY->value))
|
||||
->type(Type::STRING)
|
||||
->min(1)
|
||||
->max(parent::SIZE_TEXT),
|
||||
|
||||
(new Rules(WorkTable::IS_LISTED->value))
|
||||
->type(Type::BOOLEAN),
|
||||
|
||||
(new Rules(WorkTable::DATE_MODIFIED->value))
|
||||
->type(Type::NUMBER)
|
||||
->min(1)
|
||||
->max(parent::SIZE_UINT8)
|
||||
->default(time()),
|
||||
|
||||
(new Rules(WorkTable::DATE_CREATED->value))
|
||||
->type(Type::NUMBER)
|
||||
->min(1)
|
||||
->max(parent::SIZE_UINT8)
|
||||
]);
|
||||
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
// Generate a slug URL from string
|
||||
private static function gen_slug(string $input): string {
|
||||
return strtolower(trim(preg_replace('/[^A-Za-z0-9-]+/', '-', $input)));
|
||||
}
|
||||
|
||||
// Compute and return modeled year, month, and day from Unix timestamp in request body
|
||||
private static function gen_date_created(): array {
|
||||
return [
|
||||
WorkTable::DATE_YEAR->value => date("Y", $_POST[WorkTable::DATE_CREATED->value]),
|
||||
WorkTable::DATE_MONTH ->value => date("n", $_POST[WorkTable::DATE_CREATED->value]),
|
||||
WorkTable::DATE_DAY->value => date("j", $_POST[WorkTable::DATE_CREATED->value])
|
||||
];
|
||||
}
|
||||
|
||||
private function get_entity_by_id(string $id): Response {
|
||||
return (new Call(Endpoints::WORK->value))->params([
|
||||
WorkTable::ID->value => $id
|
||||
])->get();
|
||||
}
|
||||
|
||||
public function main(): Response {
|
||||
// Use copy of request body as entity
|
||||
$entity = $_POST;
|
||||
|
||||
// Generate a new slug id from title if changed
|
||||
if ($_POST[WorkTable::TITLE->value]) {
|
||||
$slug = $_POST[WorkTable::TITLE->value];
|
||||
|
||||
// Bail out if the slug generated from the new tite already exist
|
||||
if ($this->get_entity_by_id($slug)) {
|
||||
return new Response("An entity with this title already exist", 409);
|
||||
}
|
||||
|
||||
// Add the new slug to update entity
|
||||
$entity[WorkTable::ID] = $slug;
|
||||
}
|
||||
|
||||
// Generate new work date fields from timestamp
|
||||
if ($_POST[WorkTable::DATE_CREATED->value]) {
|
||||
array_merge($entity, self::gen_date_created());
|
||||
}
|
||||
|
||||
// Update entity by existing id
|
||||
return $this->db->for(WorkTable::NAME)->where([WorkTable::ID->value => $_GET[WorkTable::ID->value]])->update($entity) === true
|
||||
? new Response($_GET[WorkTable::ID->value])
|
||||
: new Response("Failed to update entity", 500);
|
||||
}
|
||||
}
|
106
endpoints/work/POST.php
Normal file
106
endpoints/work/POST.php
Normal file
|
@ -0,0 +1,106 @@
|
|||
<?php
|
||||
|
||||
use Reflect\Call;
|
||||
use Reflect\{Response, Path};
|
||||
use ReflectRules\{Ruleset, Rules, Type};
|
||||
|
||||
use VLW\API\Endpoints;
|
||||
use VLW\Database\Database;
|
||||
use VLW\Database\Tables\Work\{
|
||||
WorkTable,
|
||||
PermalinksTable
|
||||
};
|
||||
|
||||
require_once Path::root("src/Endpoints.php");
|
||||
require_once Path::root("src/Database/Database.php");
|
||||
require_once Path::root("src/Database/Tables/Work/Work.php");
|
||||
require_once Path::root("src/Database/Tables/Work/WorkPermalinks.php");
|
||||
|
||||
class POST_Work extends Database {
|
||||
protected Ruleset $ruleset;
|
||||
|
||||
public function __construct() {
|
||||
$this->ruleset = new Ruleset(strict: true);
|
||||
|
||||
$this->ruleset->POST([
|
||||
(new Rules(WorkTable::TITLE->value))
|
||||
->type(Type::STRING)
|
||||
->min(3)
|
||||
->max(parent::SIZE_VARCHAR)
|
||||
->default(null),
|
||||
|
||||
(new Rules(WorkTable::SUMMARY->value))
|
||||
->type(Type::STRING)
|
||||
->min(1)
|
||||
->max(parent::SIZE_TEXT)
|
||||
->default(null),
|
||||
|
||||
(new Rules(WorkTable::IS_LISTED->value))
|
||||
->type(Type::BOOLEAN)
|
||||
->default(false),
|
||||
|
||||
(new Rules(WorkTable::DATE_CREATED->value))
|
||||
->type(Type::NUMBER)
|
||||
->min(1)
|
||||
->max(parent::SIZE_UINT8)
|
||||
->default(time())
|
||||
]);
|
||||
|
||||
$this->ruleset->validate_or_exit();
|
||||
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
// Generate a slug URL from string
|
||||
private static function gen_slug(string $input): string {
|
||||
return strtolower(trim(preg_replace('/[^A-Za-z0-9-]+/', '-', $input)));
|
||||
}
|
||||
|
||||
// Compute and return modeled year, month, and day from a Unix timestamp
|
||||
private static function gen_date_created(): array {
|
||||
// Use provided timestamp in request
|
||||
$date_created = $_POST[WorkTable::DATE_CREATED->value];
|
||||
|
||||
return [
|
||||
WorkTable::DATE_YEAR->value => date("Y", $date_created),
|
||||
WorkTable::DATE_MONTH ->value => date("n", $date_created),
|
||||
WorkTable::DATE_DAY->value => date("j", $date_created)
|
||||
];
|
||||
}
|
||||
|
||||
private function get_entity_by_id(string $id): Response {
|
||||
return (new Call(Endpoints::WORK->value))->params([
|
||||
WorkTable::ID->value => $id
|
||||
])->get();
|
||||
}
|
||||
|
||||
public function main(): Response {
|
||||
// Use copy of request body as entity
|
||||
$entity = $_POST;
|
||||
|
||||
// Generate URL slug from title text or UUID if undefined
|
||||
$entity[WorkTable::ID->value] = $_POST[WorkTable::TITLE->value]
|
||||
? self::gen_slug($_POST[WorkTable::TITLE->value])
|
||||
: parent::gen_uuid4();
|
||||
|
||||
// Bail out here if a work entry with id had been created already
|
||||
if ($this->get_entity_by_id($entity[WorkTable::ID->value])->ok) {
|
||||
return new Response("An entity with id '{$slug}' already exist", 409);
|
||||
}
|
||||
|
||||
// Generate the necessary date fields
|
||||
array_merge($entity, self::gen_date_created());
|
||||
|
||||
// Let's try to insert the new entity
|
||||
if (!$this->db->for(WorkTable::NAME)->insert($entity)) {
|
||||
return new Response("Failed to insert work entry", 500);
|
||||
}
|
||||
|
||||
// Generate permalink for new entity
|
||||
return (new Call(Endpoints::WORK_PERMALINKS->value))->post([
|
||||
PermalinksTable::ID => $entity[WorkTable::ID->value],
|
||||
PermalinksTable::REF_WORK_ID => $entity[WorkTable::ID->value],
|
||||
PermalinksTable::DATE_CREATED => time()
|
||||
]);
|
||||
}
|
||||
}
|
32
endpoints/work/actions/DELETE.php
Normal file
32
endpoints/work/actions/DELETE.php
Normal file
|
@ -0,0 +1,32 @@
|
|||
<?php
|
||||
|
||||
use Reflect\{Response, Path};
|
||||
use ReflectRules\{Ruleset, Rules, Type};
|
||||
|
||||
use const VLW\API\RESP_DELETE_OK;
|
||||
use VLW\Database\Database;
|
||||
use VLW\Database\Tables\Work\ActionsTable;
|
||||
|
||||
require_once Path::root("src/Database/Database.php");
|
||||
require_once Path::root("src/Database/Tables/WorkActions.php");
|
||||
|
||||
class DELETE_WorkActions extends Database {
|
||||
protected Ruleset $ruleset;
|
||||
|
||||
public function __construct() {
|
||||
parent::__construct();
|
||||
$this->ruleset = new Ruleset(strict: true);
|
||||
|
||||
$this->ruleset->POST([
|
||||
(new Rules(ActionsTable::REF_WORK_ID->value))
|
||||
->min(1)
|
||||
->max(parent::SIZE_VARCHAR)
|
||||
]);
|
||||
}
|
||||
|
||||
public function main(): Response {
|
||||
return $this->db->for(ActionsTable::NAME)->delete($_POST) === true
|
||||
? new Response(RESP_DELETE_OK)
|
||||
: new Response("Failed to delete action for work entity", 500);
|
||||
}
|
||||
}
|
72
endpoints/work/actions/POST.php
Normal file
72
endpoints/work/actions/POST.php
Normal file
|
@ -0,0 +1,72 @@
|
|||
<?php
|
||||
|
||||
use Reflect\Call;
|
||||
use Reflect\{Response, Path};
|
||||
use ReflectRules\{Ruleset, Rules, Type};
|
||||
|
||||
use VLW\API\Endpoints;
|
||||
use VLW\Database\Database;
|
||||
use VLW\Database\Tables\Work\{
|
||||
WorkTable,
|
||||
ActionsTable
|
||||
};
|
||||
|
||||
require_once Path::root("src/Endpoints.php");
|
||||
require_once Path::root("src/Database/Database.php");
|
||||
require_once Path::root("src/Database/Tables/Work/Work.php");
|
||||
require_once Path::root("src/Database/Tables/Work/WorkActions.php");
|
||||
|
||||
class POST_WorkActions extends Database {
|
||||
protected Ruleset $ruleset;
|
||||
|
||||
public function __construct() {
|
||||
$this->ruleset = new Ruleset(strict: true);
|
||||
|
||||
$this->ruleset->POST([
|
||||
(new Rules(ActionsTable::REF_WORK_ID->value))
|
||||
->required()
|
||||
->min(1)
|
||||
->max(parent::SIZE_VARCHAR),
|
||||
|
||||
(new Rules(ActionsTable::DISPLAY_TEXT->value))
|
||||
->required()
|
||||
->type(Type::STRING)
|
||||
->min(1)
|
||||
->max(parent::SIZE_VARCHAR),
|
||||
|
||||
(new Rules(ActionsTable::HREF->value))
|
||||
->required()
|
||||
->type(Type::STRING)
|
||||
->type(Type::NULL)
|
||||
->min(1)
|
||||
->max(parent::SIZE_VARCHAR),
|
||||
|
||||
(new Rules(ActionsTable::CLASS_LIST->value))
|
||||
->type(Type::ARRAY)
|
||||
->min(1)
|
||||
->default([])
|
||||
]);
|
||||
|
||||
$this->ruleset->validate_or_exit();
|
||||
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
private static function get_entity(): Response {
|
||||
return (new Call(Endpoints::WORK->value))->params([
|
||||
WorkTable::ID->value => $_POST[ActionsTable::REF_WORK_ID->value]
|
||||
])->get();
|
||||
}
|
||||
|
||||
public function main(): Response {
|
||||
// Bail out if work entity could not be fetched
|
||||
$entity = self::get_entity();
|
||||
if (!$entity->ok) {
|
||||
return $entity;
|
||||
}
|
||||
|
||||
return $this->db->for(ActionsTable::NAME)->insert($_POST) === true
|
||||
? new Response($_POST[ActionsTable::REF_WORK_ID->value], 201)
|
||||
: new Response("Failed to add action to work entity", 500);
|
||||
}
|
||||
}
|
48
endpoints/work/permalinks/GET.php
Normal file
48
endpoints/work/permalinks/GET.php
Normal file
|
@ -0,0 +1,48 @@
|
|||
<?php
|
||||
|
||||
use Reflect\{Response, Path};
|
||||
use ReflectRules\{Ruleset, Rules, Type};
|
||||
|
||||
use VLW\Database\Database;
|
||||
use VLW\Database\Tables\Work\PermalinksTable;
|
||||
|
||||
require_once Path::root("src/Database/Database.php");
|
||||
require_once Path::root("src/Database/Tables/Work/WorkPermalinks.php");
|
||||
|
||||
class GET_WorkPermalinks extends Database {
|
||||
protected Ruleset $ruleset;
|
||||
|
||||
public function __construct() {
|
||||
$this->ruleset = new Ruleset(strict: true);
|
||||
|
||||
$this->ruleset->GET([
|
||||
(new Rules(PermalinksTable::ID->value))
|
||||
->type(Type::STRING)
|
||||
->min(1)
|
||||
->max(parent::SIZE_VARCHAR),
|
||||
|
||||
(new Rules(PermalinksTable::REF_WORK_ID->value))
|
||||
->type(Type::STRING)
|
||||
->min(1)
|
||||
->max(parent::SIZE_VARCHAR)
|
||||
]);
|
||||
|
||||
$this->ruleset->validate_or_exit();
|
||||
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
public function main(): Response {
|
||||
$response = $this->db->for(PermalinksTable::NAME)
|
||||
->where($_GET)
|
||||
->select([
|
||||
PermalinksTable::ID->value,
|
||||
PermalinksTable::REF_WORK_ID->value,
|
||||
PermalinksTable::DATE_CREATED->value
|
||||
]);
|
||||
|
||||
return $response->num_rows > 0
|
||||
? new Response($response->fetch_all(MYSQLI_ASSOC))
|
||||
: new Response([], 404);
|
||||
}
|
||||
}
|
61
endpoints/work/permalinks/POST.php
Normal file
61
endpoints/work/permalinks/POST.php
Normal file
|
@ -0,0 +1,61 @@
|
|||
<?php
|
||||
|
||||
use Reflect\Call;
|
||||
use Reflect\{Response, Path};
|
||||
use ReflectRules\{Ruleset, Rules, Type};
|
||||
|
||||
use VLW\Database\Database;
|
||||
use VLW\Database\Tables\Work\PermalinksTable;
|
||||
|
||||
require_once Path::root("src/Database/Database.php");
|
||||
require_once Path::root("src/Database/Tables/Work/WorkPermalinks.php");
|
||||
|
||||
class POST_WorkPermalinks extends Database {
|
||||
protected Ruleset $ruleset;
|
||||
|
||||
public function __construct() {
|
||||
$this->ruleset = new Ruleset(strict: true);
|
||||
|
||||
$this->ruleset->POST([
|
||||
(new Rules(PermalinksTable::ID->value))
|
||||
->required()
|
||||
->type(Type::STRING)
|
||||
->min(1)
|
||||
->max(parent::SIZE_VARCHAR),
|
||||
|
||||
(new Rules(PermalinksTable::REF_WORK_ID->value))
|
||||
->required()
|
||||
->type(Type::STRING)
|
||||
->min(1)
|
||||
->max(parent::SIZE_VARCHAR),
|
||||
|
||||
(new Rules(PermalinksTable::DATE_CREATED->value))
|
||||
->type(Type::NUMBER)
|
||||
->min(1)
|
||||
->max(parent::SIZE_UINT8)
|
||||
->default(time())
|
||||
]);
|
||||
|
||||
$this->ruleset->validate_or_exit();
|
||||
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
private static function get_entity(): Response {
|
||||
return (new Call(Endpoints::WORK->value))->params([
|
||||
WorkTable::ID->value => $_POST[TagsTable::REF_WORK_ID->value]
|
||||
])->get();
|
||||
}
|
||||
|
||||
public function main(): Response {
|
||||
// Bail out if work entity could not be fetched
|
||||
$entity = self::get_entity();
|
||||
if (!$entity->ok) {
|
||||
return $entity;
|
||||
}
|
||||
|
||||
return $this->db->for(PermalinksTable::NAME)->insert($_POST) === true
|
||||
? new Response($_POST[PermalinksTable::ID->value], 201)
|
||||
: new Response("Failed to add permalink to work entity", 500);
|
||||
}
|
||||
}
|
38
endpoints/work/tags/DELETE.php
Normal file
38
endpoints/work/tags/DELETE.php
Normal file
|
@ -0,0 +1,38 @@
|
|||
<?php
|
||||
|
||||
use Reflect\{Response, Path};
|
||||
use ReflectRules\{Ruleset, Rules, Type};
|
||||
|
||||
use const VLW\API\RESP_DELETE_OK;
|
||||
use VLW\Database\Database;
|
||||
use VLW\Database\Tables\Work\TagsTable;
|
||||
|
||||
require_once Path::root("src/Database/Database.php");
|
||||
require_once Path::root("src/Database/Tables/Work/WorkTags.php");
|
||||
|
||||
class DELETE_WorkTags extends Database {
|
||||
private Ruleset $ruleset;
|
||||
|
||||
public function __construct() {
|
||||
$this->ruleset = new Ruleset(strict: true);
|
||||
|
||||
$this->ruleset->GET([
|
||||
(new Rules(TagsTable::REF_WORK_ID->value))
|
||||
->min(1)
|
||||
->max(parent::SIZE_VARCHAR),
|
||||
|
||||
(new Rules(TagsTable::NAME->value))
|
||||
->type(Type::ENUM, TagsNameEnum::names())
|
||||
]);
|
||||
|
||||
$this->ruleset->validate_or_exit();
|
||||
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
public function main(): Response {
|
||||
return $this->db->for(TagsTable::NAME)->delete($_POST) === true
|
||||
? new Response(RESP_DELETE_OK)
|
||||
: new Response("Failed to delete value from document", 500);
|
||||
}
|
||||
}
|
59
endpoints/work/tags/POST.php
Normal file
59
endpoints/work/tags/POST.php
Normal file
|
@ -0,0 +1,59 @@
|
|||
<?php
|
||||
|
||||
use Reflect\Call;
|
||||
use Reflect\{Response, Path};
|
||||
use ReflectRules\{Ruleset, Rules, Type};
|
||||
|
||||
use VLW\API\Endpoints;
|
||||
use VLW\Database\Database;
|
||||
use VLW\Database\Tables\Work\{
|
||||
WorkTable,
|
||||
TagsTable,
|
||||
TagsNameEnum
|
||||
};
|
||||
|
||||
require_once Path::root("src/Endpoints.php");
|
||||
require_once Path::root("src/Database/Database.php");
|
||||
require_once Path::root("src/Database/Tables/Work/Work.php");
|
||||
require_once Path::root("src/Database/Tables/Work/WorkTags.php");
|
||||
|
||||
class POST_WorkTags extends Database {
|
||||
protected Ruleset $ruleset;
|
||||
|
||||
public function __construct() {
|
||||
$this->ruleset = new Ruleset(strict: true);
|
||||
|
||||
$this->ruleset->POST([
|
||||
(new Rules(TagsTable::REF_WORK_ID->value))
|
||||
->required()
|
||||
->min(1)
|
||||
->max(parent::SIZE_VARCHAR),
|
||||
|
||||
(new Rules(TagsTable::NAME->value))
|
||||
->required()
|
||||
->type(Type::ENUM, TagsNameEnum::names())
|
||||
]);
|
||||
|
||||
$this->ruleset->validate_or_exit();
|
||||
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
private static function get_entity(): Response {
|
||||
return (new Call(Endpoints::WORK->value))->params([
|
||||
WorkTable::ID->value => $_POST[TagsTable::REF_WORK_ID->value]
|
||||
])->get();
|
||||
}
|
||||
|
||||
public function main(): Response {
|
||||
// Bail out if work entity could not be fetched
|
||||
$entity = self::get_entity();
|
||||
if (!$entity->ok) {
|
||||
return $entity;
|
||||
}
|
||||
|
||||
return $this->db->for(TagsTable::NAME)->insert($_POST) === true
|
||||
? new Response($_POST[TagsTable::REF_WORK_ID->value], 201)
|
||||
: new Response("Failed to add tag to work entity", 500);
|
||||
}
|
||||
}
|
|
@ -121,10 +121,7 @@ section.timeline .items .item img {
|
|||
}
|
||||
|
||||
section.timeline .items .item .actions {
|
||||
display: flex;
|
||||
align-items: baseline;
|
||||
margin-top: 7px;
|
||||
gap: var(--padding);
|
||||
}
|
||||
|
||||
/* # Size queries */
|
||||
|
@ -169,10 +166,6 @@ section.timeline .items .item .actions {
|
|||
border-top-color: rgba(var(--primer-color-accent), .2);
|
||||
}
|
||||
|
||||
section.timeline .items .item .actions {
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
section.timeline .year:first-of-type .month:first-of-type .day:first-of-type .items .item:first-of-type {
|
||||
margin-top: var(--padding);
|
||||
}
|
||||
|
|
1
public/assets/js/modules/npm/Elevent.mjs
Symbolic link
1
public/assets/js/modules/npm/Elevent.mjs
Symbolic link
|
@ -0,0 +1 @@
|
|||
../../../../../node_modules/elevent/src/Elevent.mjs
|
|
@ -1,2 +0,0 @@
|
|||
User-agent: *
|
||||
Disallow:
|
Loading…
Add table
Reference in a new issue