mirror of
https://codeberg.org/vlw/vlw.se.git
synced 2025-09-13 21:13:40 +02:00
feat: major post-launch fixes and bump of reflect/client
to 3.0.6 (#9)
This commit is contained in:
parent
140132fa72
commit
150559b075
22 changed files with 471 additions and 264 deletions
|
@ -1,7 +1,14 @@
|
||||||
{
|
{
|
||||||
"require": {
|
"require": {
|
||||||
|
"local/api.endpoints": "1.0.0-dev",
|
||||||
"reflect/plugin-rules": "^1.5",
|
"reflect/plugin-rules": "^1.5",
|
||||||
"victorwesterlund/innodb-fk": "^1.0",
|
|
||||||
"victorwesterlund/xenum": "^1.1"
|
"victorwesterlund/xenum": "^1.1"
|
||||||
}
|
},
|
||||||
|
"minimum-stability": "dev",
|
||||||
|
"repositories": [
|
||||||
|
{
|
||||||
|
"type": "path",
|
||||||
|
"url": "src/packages/Endpoints"
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
|
|
111
api/composer.lock
generated
111
api/composer.lock
generated
|
@ -4,8 +4,33 @@
|
||||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||||
"This file is @generated automatically"
|
"This file is @generated automatically"
|
||||||
],
|
],
|
||||||
"content-hash": "ba3fa8466aa20501e06050d722c86a35",
|
"content-hash": "9da96ba90ef20d885034442b30dce0a3",
|
||||||
"packages": [
|
"packages": [
|
||||||
|
{
|
||||||
|
"name": "local/api.endpoints",
|
||||||
|
"version": "1.0.0-dev",
|
||||||
|
"dist": {
|
||||||
|
"type": "path",
|
||||||
|
"url": "src/packages/Endpoints",
|
||||||
|
"reference": "89b7b9a4cc504abddb4aeec8e05a95c9d9087575"
|
||||||
|
},
|
||||||
|
"type": "library",
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"VLW\\API\\": "src/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Victor Westerlund",
|
||||||
|
"email": "victor@vlw.se"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "Endpoint pathmappings for VLW API",
|
||||||
|
"transport-options": {
|
||||||
|
"relative": true
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "reflect/plugin-rules",
|
"name": "reflect/plugin-rules",
|
||||||
"version": "1.5.0",
|
"version": "1.5.0",
|
||||||
|
@ -43,84 +68,6 @@
|
||||||
},
|
},
|
||||||
"time": "2024-01-17T11:07:44+00:00"
|
"time": "2024-01-17T11:07:44+00:00"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"name": "victorwesterlund/innodb-fk",
|
|
||||||
"version": "1.0.3",
|
|
||||||
"source": {
|
|
||||||
"type": "git",
|
|
||||||
"url": "https://github.com/VictorWesterlund/php-libinnodb-fk.git",
|
|
||||||
"reference": "ffea024f16613e6d6857c93200185cf0a20a9640"
|
|
||||||
},
|
|
||||||
"dist": {
|
|
||||||
"type": "zip",
|
|
||||||
"url": "https://api.github.com/repos/VictorWesterlund/php-libinnodb-fk/zipball/ffea024f16613e6d6857c93200185cf0a20a9640",
|
|
||||||
"reference": "ffea024f16613e6d6857c93200185cf0a20a9640",
|
|
||||||
"shasum": ""
|
|
||||||
},
|
|
||||||
"require": {
|
|
||||||
"victorwesterlund/libmysqldriver": "^3.0",
|
|
||||||
"victorwesterlund/xenum": "^1.0"
|
|
||||||
},
|
|
||||||
"type": "library",
|
|
||||||
"autoload": {
|
|
||||||
"psr-4": {
|
|
||||||
"victorwesterlund\\": "src/"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"notification-url": "https://packagist.org/downloads/",
|
|
||||||
"license": [
|
|
||||||
"GPL-3.0-only"
|
|
||||||
],
|
|
||||||
"authors": [
|
|
||||||
{
|
|
||||||
"name": "Victor Westerlund",
|
|
||||||
"email": "victor.vesterlund@gmail.com"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"description": "Retrievie and optionally resolves foreign keys in a MySQL/MariaDB InnoDB database",
|
|
||||||
"support": {
|
|
||||||
"issues": "https://github.com/VictorWesterlund/php-libinnodb-fk/issues",
|
|
||||||
"source": "https://github.com/VictorWesterlund/php-libinnodb-fk/tree/1.0.3"
|
|
||||||
},
|
|
||||||
"time": "2023-11-02T13:26:34+00:00"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "victorwesterlund/libmysqldriver",
|
|
||||||
"version": "3.5.1",
|
|
||||||
"source": {
|
|
||||||
"type": "git",
|
|
||||||
"url": "https://github.com/VictorWesterlund/php-libmysqldriver.git",
|
|
||||||
"reference": "73b5d858ffa8d83c5cbe6b3d3de4af314a5ffbe5"
|
|
||||||
},
|
|
||||||
"dist": {
|
|
||||||
"type": "zip",
|
|
||||||
"url": "https://api.github.com/repos/VictorWesterlund/php-libmysqldriver/zipball/73b5d858ffa8d83c5cbe6b3d3de4af314a5ffbe5",
|
|
||||||
"reference": "73b5d858ffa8d83c5cbe6b3d3de4af314a5ffbe5",
|
|
||||||
"shasum": ""
|
|
||||||
},
|
|
||||||
"type": "library",
|
|
||||||
"autoload": {
|
|
||||||
"psr-4": {
|
|
||||||
"libmysqldriver\\": "src/"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"notification-url": "https://packagist.org/downloads/",
|
|
||||||
"license": [
|
|
||||||
"GPL-3.0-only"
|
|
||||||
],
|
|
||||||
"authors": [
|
|
||||||
{
|
|
||||||
"name": "Victor Westerlund",
|
|
||||||
"email": "victor.vesterlund@gmail.com"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"description": "Abstraction library for common mysqli features",
|
|
||||||
"support": {
|
|
||||||
"issues": "https://github.com/VictorWesterlund/php-libmysqldriver/issues",
|
|
||||||
"source": "https://github.com/VictorWesterlund/php-libmysqldriver/tree/3.5.1"
|
|
||||||
},
|
|
||||||
"time": "2024-02-26T12:51:52+00:00"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "victorwesterlund/xenum",
|
"name": "victorwesterlund/xenum",
|
||||||
"version": "1.1.1",
|
"version": "1.1.1",
|
||||||
|
@ -161,8 +108,10 @@
|
||||||
],
|
],
|
||||||
"packages-dev": [],
|
"packages-dev": [],
|
||||||
"aliases": [],
|
"aliases": [],
|
||||||
"minimum-stability": "stable",
|
"minimum-stability": "dev",
|
||||||
"stability-flags": [],
|
"stability-flags": {
|
||||||
|
"local/api.endpoints": 20
|
||||||
|
},
|
||||||
"prefer-stable": false,
|
"prefer-stable": false,
|
||||||
"prefer-lowest": false,
|
"prefer-lowest": false,
|
||||||
"platform": [],
|
"platform": [],
|
||||||
|
|
|
@ -1,17 +1,21 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
|
use Reflect\Call;
|
||||||
use Reflect\Path;
|
use Reflect\Path;
|
||||||
use Reflect\Response;
|
use Reflect\Response;
|
||||||
use ReflectRules\Type;
|
use ReflectRules\Type;
|
||||||
use ReflectRules\Rules;
|
use ReflectRules\Rules;
|
||||||
use ReflectRules\Ruleset;
|
use ReflectRules\Ruleset;
|
||||||
|
|
||||||
|
use VLW\API\Endpoints;
|
||||||
|
|
||||||
use VLW\API\Databases\VLWdb\VLWdb;
|
use VLW\API\Databases\VLWdb\VLWdb;
|
||||||
use VLW\API\Databases\VLWdb\Models\Work\WorkModel;
|
use VLW\API\Databases\VLWdb\Models\Work\WorkModel;
|
||||||
|
use VLW\API\Databases\VLWdb\Models\Work\WorkActionsModel;
|
||||||
|
|
||||||
require_once Path::root("src/databases/VLWdb.php");
|
require_once Path::root("src/databases/VLWdb.php");
|
||||||
require_once Path::root("src/databases/models/Work.php");
|
require_once Path::root("src/databases/models/Work.php");
|
||||||
|
require_once Path::root("src/databases/models/WorkActions.php");
|
||||||
|
|
||||||
class GET_Search extends VLWdb {
|
class GET_Search extends VLWdb {
|
||||||
const GET_QUERY = "q";
|
const GET_QUERY = "q";
|
||||||
|
@ -87,7 +91,15 @@
|
||||||
WorkModel::IS_LISTABLE->value => true
|
WorkModel::IS_LISTABLE->value => true
|
||||||
];
|
];
|
||||||
|
|
||||||
return $this->search(WorkModel::TABLE, $search, $conditions);
|
$results = $this->search(WorkModel::TABLE, $search, $conditions);
|
||||||
|
|
||||||
|
foreach ($results as &$result) {
|
||||||
|
$result["actions"] = (new Call(Endpoints::WORK_ACTIONS->value))
|
||||||
|
->params([WorkActionsModel::ANCHOR->value => $result[WorkModel::ID->value]])
|
||||||
|
->get()->output();
|
||||||
|
}
|
||||||
|
|
||||||
|
return $results;
|
||||||
}
|
}
|
||||||
|
|
||||||
// # Responses
|
// # Responses
|
||||||
|
|
|
@ -1,13 +1,14 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
|
use Reflect\Call;
|
||||||
use Reflect\Path;
|
use Reflect\Path;
|
||||||
|
use Reflect\Method;
|
||||||
use Reflect\Response;
|
use Reflect\Response;
|
||||||
use ReflectRules\Type;
|
use ReflectRules\Type;
|
||||||
use ReflectRules\Rules;
|
use ReflectRules\Rules;
|
||||||
use ReflectRules\Ruleset;
|
use ReflectRules\Ruleset;
|
||||||
|
|
||||||
use Reflect\Method;
|
use VLW\API\Endpoints;
|
||||||
use function Reflect\Call;
|
|
||||||
|
|
||||||
use VLW\API\Databases\VLWdb\VLWdb;
|
use VLW\API\Databases\VLWdb\VLWdb;
|
||||||
use VLW\API\Databases\VLWdb\Models\Work\WorkModel;
|
use VLW\API\Databases\VLWdb\Models\Work\WorkModel;
|
||||||
|
@ -45,19 +46,6 @@
|
||||||
return parent::is_mysqli_result($resp) ? $resp->fetch_all(MYSQLI_ASSOC) : [];
|
return parent::is_mysqli_result($resp) ? $resp->fetch_all(MYSQLI_ASSOC) : [];
|
||||||
}
|
}
|
||||||
|
|
||||||
private function fetch_row_actions(string $id): array {
|
|
||||||
$resp = $this->db->for(WorkActionsModel::TABLE)
|
|
||||||
->where([WorkActionsModel::ANCHOR->value => $id])
|
|
||||||
->select([
|
|
||||||
WorkActionsModel::DISPLAY_TEXT->value,
|
|
||||||
WorkActionsModel::HREF->value,
|
|
||||||
WorkActionsModel::CLASS_LIST->value,
|
|
||||||
WorkActionsModel::EXTERNAL->value
|
|
||||||
]);
|
|
||||||
|
|
||||||
return parent::is_mysqli_result($resp) ? $resp->fetch_all(MYSQLI_ASSOC) : [];
|
|
||||||
}
|
|
||||||
|
|
||||||
// # Responses
|
// # Responses
|
||||||
|
|
||||||
// Return 422 Unprocessable Content error if request validation failed
|
// Return 422 Unprocessable Content error if request validation failed
|
||||||
|
@ -134,13 +122,11 @@
|
||||||
$rows = [];
|
$rows = [];
|
||||||
while ($row = $resp->fetch_assoc()) {
|
while ($row = $resp->fetch_assoc()) {
|
||||||
$row["tags"] = $this->fetch_row_tags($row["id"]);
|
$row["tags"] = $this->fetch_row_tags($row["id"]);
|
||||||
$row["actions"] = $this->fetch_row_actions($row["id"]);
|
|
||||||
|
|
||||||
// Resolve media entities in srcset
|
// Fetch actions for work entity by id from endpoint
|
||||||
$srcset = Call("media/srcset?id={$row[WorkModel::COVER_SRCSET->value]}", Method::GET);
|
$row["actions"] = (new Call(Endpoints::WORK_ACTIONS->value))
|
||||||
|
->params([WorkActionsModel::ANCHOR->value => $row[WorkModel::ID->value]])
|
||||||
// Mutate key on current row
|
->get()->output();
|
||||||
$row[WorkModel::COVER_SRCSET->value] = $srcset->ok ? $srcset->output() : [];
|
|
||||||
|
|
||||||
$rows[] = $row;
|
$rows[] = $row;
|
||||||
}
|
}
|
||||||
|
|
67
api/endpoints/work/actions/GET.php
Normal file
67
api/endpoints/work/actions/GET.php
Normal file
|
@ -0,0 +1,67 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
use Reflect\Path;
|
||||||
|
use Reflect\Response;
|
||||||
|
use ReflectRules\Type;
|
||||||
|
use ReflectRules\Rules;
|
||||||
|
use ReflectRules\Ruleset;
|
||||||
|
|
||||||
|
use VLW\API\Databases\VLWdb\VLWdb;
|
||||||
|
use VLW\API\Databases\VLWdb\Models\Work\WorkActionsModel;
|
||||||
|
|
||||||
|
require_once Path::root("src/databases/VLWdb.php");
|
||||||
|
require_once Path::root("src/databases/models/WorkActions.php");
|
||||||
|
|
||||||
|
class GET_WorkActions extends VLWdb {
|
||||||
|
protected Ruleset $ruleset;
|
||||||
|
|
||||||
|
public function __construct() {
|
||||||
|
parent::__construct();
|
||||||
|
$this->ruleset = new Ruleset(strict: true);
|
||||||
|
|
||||||
|
$this->ruleset->GET([
|
||||||
|
(new Rules(WorkActionsModel::ANCHOR->value))
|
||||||
|
->required()
|
||||||
|
->type(Type::STRING)
|
||||||
|
->min(1)
|
||||||
|
->max(parent::MYSQL_VARCHAR_MAX_LENGTH)
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// # Responses
|
||||||
|
|
||||||
|
// Return 422 Unprocessable Content error if request validation failed
|
||||||
|
private function resp_rules_invalid(): Response {
|
||||||
|
return new Response($this->ruleset->get_errors(), 422);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return a 503 Service Unavailable error if something went wrong with the database call
|
||||||
|
private function resp_database_error(): Response {
|
||||||
|
return new Response("Failed to get work data, please try again later", 503);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function main(): Response {
|
||||||
|
// Bail out if request validation failed
|
||||||
|
if (!$this->ruleset->is_valid()) {
|
||||||
|
return $this->resp_rules_invalid();
|
||||||
|
}
|
||||||
|
|
||||||
|
$resp = $this->db->for(WorkActionsModel::TABLE)
|
||||||
|
->where([WorkActionsModel::ANCHOR->value => $_GET[WorkActionsModel::ANCHOR->value]])
|
||||||
|
->select([
|
||||||
|
WorkActionsModel::DISPLAY_TEXT->value,
|
||||||
|
WorkActionsModel::HREF->value,
|
||||||
|
WorkActionsModel::CLASS_LIST->value,
|
||||||
|
WorkActionsModel::EXTERNAL->value
|
||||||
|
]);
|
||||||
|
|
||||||
|
// Bail out if something went wrong retrieving rows from the database
|
||||||
|
if (!parent::is_mysqli_result($resp)) {
|
||||||
|
return $this->resp_database_error();
|
||||||
|
}
|
||||||
|
|
||||||
|
return $resp->num_rows > 0
|
||||||
|
? new Response($resp->fetch_all(MYSQLI_ASSOC))
|
||||||
|
: new Response([]);
|
||||||
|
}
|
||||||
|
}
|
|
@ -5,6 +5,8 @@
|
||||||
use libmysqldriver\MySQL;
|
use libmysqldriver\MySQL;
|
||||||
|
|
||||||
class VLWdb {
|
class VLWdb {
|
||||||
|
const UUID_LENGTH = 36;
|
||||||
|
|
||||||
const MYSQL_TEXT_MAX_LENGTH = 65538;
|
const MYSQL_TEXT_MAX_LENGTH = 65538;
|
||||||
const MYSQL_VARCHAR_MAX_LENGTH = 255;
|
const MYSQL_VARCHAR_MAX_LENGTH = 255;
|
||||||
const MYSQL_INT_MAX_LENGHT = 2147483647;
|
const MYSQL_INT_MAX_LENGHT = 2147483647;
|
||||||
|
|
17
api/src/packages/Endpoints/composer.json
Normal file
17
api/src/packages/Endpoints/composer.json
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
{
|
||||||
|
"name": "local/api.endpoints",
|
||||||
|
"description": "Endpoint pathmappings for VLW API",
|
||||||
|
"type": "library",
|
||||||
|
"version": "1.0.0-dev",
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Victor Westerlund",
|
||||||
|
"email": "victor@vlw.se"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"VLW\\API\\": "src/"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
11
api/src/packages/Endpoints/src/Endpoints.php
Normal file
11
api/src/packages/Endpoints/src/Endpoints.php
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace VLW\API;
|
||||||
|
|
||||||
|
enum Endpoints: string {
|
||||||
|
case WORK = "/work";
|
||||||
|
case SEARCH = "/search";
|
||||||
|
case MESSAGES = "/messages";
|
||||||
|
case WORK_TAGS = "/work/tags";
|
||||||
|
case WORK_ACTIONS = "/work/actions";
|
||||||
|
}
|
|
@ -14,6 +14,7 @@
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
font-family: "Roboto Mono", sans-serif;
|
font-family: "Roboto Mono", sans-serif;
|
||||||
color: inherit;
|
color: inherit;
|
||||||
|
font-size: inherit;
|
||||||
}
|
}
|
||||||
|
|
||||||
::-webkit-scrollbar {
|
::-webkit-scrollbar {
|
||||||
|
@ -29,6 +30,7 @@ body {
|
||||||
color: white;
|
color: white;
|
||||||
overflow-x: hidden;
|
overflow-x: hidden;
|
||||||
min-height: 100svh;
|
min-height: 100svh;
|
||||||
|
font-size: 15px;
|
||||||
}
|
}
|
||||||
|
|
||||||
body.search-dialog-open {
|
body.search-dialog-open {
|
||||||
|
@ -53,10 +55,22 @@ a {
|
||||||
text-decoration-color: var(--color-accent);
|
text-decoration-color: var(--color-accent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
font-size: 30px;
|
||||||
|
color: var(--color-accent);
|
||||||
|
}
|
||||||
|
|
||||||
|
h2 {
|
||||||
|
font-size: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
h3 {
|
||||||
|
font-size: 25px;
|
||||||
|
}
|
||||||
|
|
||||||
/* ## Buttons */
|
/* ## Buttons */
|
||||||
|
|
||||||
button {
|
button {
|
||||||
font-size: inherit;
|
|
||||||
padding: calc(var(--padding) / 2) var(--padding);
|
padding: calc(var(--padding) / 2) var(--padding);
|
||||||
color: white;
|
color: white;
|
||||||
border: solid 2px white;
|
border: solid 2px white;
|
||||||
|
@ -161,7 +175,7 @@ searchbox {
|
||||||
padding: var(--padding);
|
padding: var(--padding);
|
||||||
gap: var(--padding);
|
gap: var(--padding);
|
||||||
fill: var(--color-accent);
|
fill: var(--color-accent);
|
||||||
font-size: 14px;
|
font-size: 13px;
|
||||||
color: rgba(255, 255, 255, .5);
|
color: rgba(255, 255, 255, .5);
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
@ -218,7 +232,7 @@ search input {
|
||||||
border: none;
|
border: none;
|
||||||
outline: none;
|
outline: none;
|
||||||
color: black;
|
color: black;
|
||||||
font-size: 18px;
|
font-size: 16px;
|
||||||
padding: var(--padding) calc(var(--padding) * 1.5);
|
padding: var(--padding) calc(var(--padding) * 1.5);
|
||||||
background-color: rgba(255, 255, 255, .05);
|
background-color: rgba(255, 255, 255, .05);
|
||||||
box-shadow: 0 5px 70px 10px rgba(0, 0, 0, .3);
|
box-shadow: 0 5px 70px 10px rgba(0, 0, 0, .3);
|
||||||
|
|
|
@ -13,17 +13,6 @@ main {
|
||||||
|
|
||||||
/* # Sections */
|
/* # Sections */
|
||||||
|
|
||||||
/* ## Into */
|
|
||||||
|
|
||||||
section.intro h2 {
|
|
||||||
font-size: 25px;
|
|
||||||
}
|
|
||||||
|
|
||||||
section.intro h1 {
|
|
||||||
font-size: 40px;
|
|
||||||
color: var(--color-accent);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ## Divider */
|
/* ## Divider */
|
||||||
|
|
||||||
main > hr {
|
main > hr {
|
||||||
|
@ -38,12 +27,8 @@ section.about {
|
||||||
gap: calc(var(--padding) / 2);
|
gap: calc(var(--padding) / 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
section.about {
|
|
||||||
font-size: 16px;
|
|
||||||
}
|
|
||||||
|
|
||||||
section.about p:first-of-type:first-letter {
|
section.about p:first-of-type:first-letter {
|
||||||
font-size: 1.5rem;
|
font-size: 1.8rem;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
margin-right: .1rem;
|
margin-right: .1rem;
|
||||||
color: var(--color-accent);
|
color: var(--color-accent);
|
||||||
|
@ -73,7 +58,7 @@ div.interests {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
font-size: 60px;
|
font-size: 50px;
|
||||||
color: var(--color-accent);
|
color: var(--color-accent);
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
|
|
|
@ -46,7 +46,6 @@ section.social social p {
|
||||||
transform: translate(0, 0);
|
transform: translate(0, 0);
|
||||||
background-color: rgba(var(--primer-color-accent), .1);
|
background-color: rgba(var(--primer-color-accent), .1);
|
||||||
padding: 5px 10px;
|
padding: 5px 10px;
|
||||||
font-size: 17px;
|
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
border-radius: 6px;
|
border-radius: 6px;
|
||||||
|
@ -98,7 +97,6 @@ section.form :is(input, textarea) {
|
||||||
min-width: 100%;
|
min-width: 100%;
|
||||||
max-width: 100%;
|
max-width: 100%;
|
||||||
color: black;
|
color: black;
|
||||||
font-size: 15px;
|
|
||||||
padding: var(--padding);
|
padding: var(--padding);
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
border: none;
|
border: none;
|
||||||
|
@ -160,7 +158,6 @@ section.form-message h3 {
|
||||||
}
|
}
|
||||||
|
|
||||||
section.form-message pre {
|
section.form-message pre {
|
||||||
font-size: 11px;
|
|
||||||
padding: var(--padding);
|
padding: var(--padding);
|
||||||
background-color: rgba(0, 0, 0, .15);
|
background-color: rgba(0, 0, 0, .15);
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,12 +38,24 @@ section.search button[type="submit"] {
|
||||||
max-width: 350px;
|
max-width: 350px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
section.search > svg {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
body:not([vv-page="/search"]) section.search {
|
body:not([vv-page="/search"]) section.search {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* # Search results */
|
/* # Search results */
|
||||||
|
|
||||||
|
section.results .result {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: calc(var(--padding) / 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ---- */
|
||||||
|
|
||||||
main > svg,
|
main > svg,
|
||||||
dialog.search search search-results > svg {
|
dialog.search search search-results > svg {
|
||||||
margin: auto;
|
margin: auto;
|
||||||
|
@ -57,7 +69,7 @@ dialog.search search search-results .empty {
|
||||||
|
|
||||||
/* ## Titles */
|
/* ## Titles */
|
||||||
|
|
||||||
section.title h2 {
|
section.title a h2 {
|
||||||
color: var(--color-accent);
|
color: var(--color-accent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -76,19 +88,6 @@ section.results.work {
|
||||||
|
|
||||||
section.results.work .result {
|
section.results.work .result {
|
||||||
padding: var(--padding);
|
padding: var(--padding);
|
||||||
background-color: rgba(255, 255, 255, .1);
|
background-color: rgba(255, 255, 255, .03);
|
||||||
border-radius: 6px;
|
border-radius: 6px;
|
||||||
}
|
|
||||||
|
|
||||||
/* # Feature queries */
|
|
||||||
|
|
||||||
@media (hover: hover) {
|
|
||||||
section.results.work .result {
|
|
||||||
transition: 300ms background-color;
|
|
||||||
}
|
|
||||||
|
|
||||||
section.results.work .result:hover {
|
|
||||||
background-color: rgba(255, 255, 255, .2);
|
|
||||||
box-shadow: 0 5px 70px 10px rgba(0, 0, 0, .3);
|
|
||||||
}
|
|
||||||
}
|
}
|
|
@ -9,7 +9,6 @@ main {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
gap: var(--padding);
|
gap: var(--padding);
|
||||||
padding: calc(var(--padding) * 1.5);
|
|
||||||
width: 100%;
|
width: 100%;
|
||||||
max-width: 1200px;
|
max-width: 1200px;
|
||||||
overflow-x: initial;
|
overflow-x: initial;
|
||||||
|
@ -114,18 +113,6 @@ section.timeline .items .item .tags .tag {
|
||||||
padding: 5px 10px;
|
padding: 5px 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
section.timeline .items .item h2 {
|
|
||||||
font-size: 30px;
|
|
||||||
}
|
|
||||||
|
|
||||||
section.timeline .items .item h3 {
|
|
||||||
font-size: 25px;
|
|
||||||
}
|
|
||||||
|
|
||||||
section.timeline .items .item p {
|
|
||||||
font-size: 16px;
|
|
||||||
}
|
|
||||||
|
|
||||||
section.timeline .items .item img {
|
section.timeline .items .item img {
|
||||||
max-width: 100%;
|
max-width: 100%;
|
||||||
height: 250px;
|
height: 250px;
|
||||||
|
@ -133,7 +120,6 @@ section.timeline .items .item img {
|
||||||
|
|
||||||
section.timeline .items .item .actions {
|
section.timeline .items .item .actions {
|
||||||
margin-top: 7px;
|
margin-top: 7px;
|
||||||
font-size: 13px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ## Note */
|
/* ## Note */
|
||||||
|
@ -174,7 +160,6 @@ section.note {
|
||||||
|
|
||||||
section.timeline .track {
|
section.timeline .track {
|
||||||
position: relative;
|
position: relative;
|
||||||
left: calc(var(--padding) * 1.5);
|
|
||||||
background: unset;
|
background: unset;
|
||||||
z-index: 10;
|
z-index: 10;
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
|
@ -194,6 +179,7 @@ section.note {
|
||||||
}
|
}
|
||||||
|
|
||||||
section.timeline .items .item {
|
section.timeline .items .item {
|
||||||
|
padding: calc(var(--padding) * 1.5) 0;
|
||||||
width: calc(100vw - (var(--padding) * 3.5));
|
width: calc(100vw - (var(--padding) * 3.5));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,17 @@
|
||||||
{
|
{
|
||||||
"require": {
|
"require": {
|
||||||
"reflect/client": "^2.1"
|
"local/api.client": "1.0.0-dev",
|
||||||
}
|
"local/api.endpoints": "1.0.0-dev"
|
||||||
|
},
|
||||||
|
"minimum-stability": "dev",
|
||||||
|
"repositories": [
|
||||||
|
{
|
||||||
|
"type": "path",
|
||||||
|
"url": "src/packages/API"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "path",
|
||||||
|
"url": "api/src/packages/Endpoints"
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
|
|
74
composer.lock
generated
74
composer.lock
generated
|
@ -4,20 +4,73 @@
|
||||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||||
"This file is @generated automatically"
|
"This file is @generated automatically"
|
||||||
],
|
],
|
||||||
"content-hash": "3e10269d358ba18734f4f011cd22c42e",
|
"content-hash": "73a61bf0308871f9dc9ad050aedfe13e",
|
||||||
"packages": [
|
"packages": [
|
||||||
|
{
|
||||||
|
"name": "local/api.client",
|
||||||
|
"version": "1.0.0-dev",
|
||||||
|
"dist": {
|
||||||
|
"type": "path",
|
||||||
|
"url": "src/packages/API",
|
||||||
|
"reference": "020275feb0e0017fa91ae0b33213bc54f35cac75"
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"reflect/client": "^3.0"
|
||||||
|
},
|
||||||
|
"type": "library",
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"VLW\\API\\": "src/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Victor Westerlund",
|
||||||
|
"email": "victor@vlw.se"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "Wrapper for vlw.se API",
|
||||||
|
"transport-options": {
|
||||||
|
"relative": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "local/api.endpoints",
|
||||||
|
"version": "1.0.0-dev",
|
||||||
|
"dist": {
|
||||||
|
"type": "path",
|
||||||
|
"url": "api/src/packages/Endpoints",
|
||||||
|
"reference": "89b7b9a4cc504abddb4aeec8e05a95c9d9087575"
|
||||||
|
},
|
||||||
|
"type": "library",
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"VLW\\API\\": "src/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Victor Westerlund",
|
||||||
|
"email": "victor@vlw.se"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "Endpoint pathmappings for VLW API",
|
||||||
|
"transport-options": {
|
||||||
|
"relative": true
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "reflect/client",
|
"name": "reflect/client",
|
||||||
"version": "2.1.4",
|
"version": "3.0.6",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/VictorWesterlund/reflect-client-php.git",
|
"url": "https://github.com/VictorWesterlund/reflect-client-php.git",
|
||||||
"reference": "47cee961d1bfdd9261a58dde753d824947e91636"
|
"reference": "89a8c041044c8c60cefafc4716d5d61b96c43e06"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/VictorWesterlund/reflect-client-php/zipball/47cee961d1bfdd9261a58dde753d824947e91636",
|
"url": "https://api.github.com/repos/VictorWesterlund/reflect-client-php/zipball/89a8c041044c8c60cefafc4716d5d61b96c43e06",
|
||||||
"reference": "47cee961d1bfdd9261a58dde753d824947e91636",
|
"reference": "89a8c041044c8c60cefafc4716d5d61b96c43e06",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"type": "library",
|
"type": "library",
|
||||||
|
@ -39,15 +92,18 @@
|
||||||
"description": "Extendable PHP interface for communicating with Reflect API over HTTP or UNIX sockets",
|
"description": "Extendable PHP interface for communicating with Reflect API over HTTP or UNIX sockets",
|
||||||
"support": {
|
"support": {
|
||||||
"issues": "https://github.com/VictorWesterlund/reflect-client-php/issues",
|
"issues": "https://github.com/VictorWesterlund/reflect-client-php/issues",
|
||||||
"source": "https://github.com/VictorWesterlund/reflect-client-php/tree/2.1.4"
|
"source": "https://github.com/VictorWesterlund/reflect-client-php/tree/3.0.6"
|
||||||
},
|
},
|
||||||
"time": "2023-08-18T14:41:31+00:00"
|
"time": "2024-04-06T14:55:04+00:00"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"packages-dev": [],
|
"packages-dev": [],
|
||||||
"aliases": [],
|
"aliases": [],
|
||||||
"minimum-stability": "stable",
|
"minimum-stability": "dev",
|
||||||
"stability-flags": [],
|
"stability-flags": {
|
||||||
|
"local/api.client": 20,
|
||||||
|
"local/api.endpoints": 20
|
||||||
|
},
|
||||||
"prefer-stable": false,
|
"prefer-stable": false,
|
||||||
"prefer-lowest": false,
|
"prefer-lowest": false,
|
||||||
"platform": [],
|
"platform": [],
|
||||||
|
|
|
@ -1,30 +1,3 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
use Reflect\Client;
|
|
||||||
use Reflect\Method;
|
|
||||||
|
|
||||||
// Connect to VLW API
|
|
||||||
function api_client(): Client {
|
|
||||||
return new Client($_ENV["api"]["base_url"], $_ENV["api"]["api_key"], https_peer_verify: $_ENV["api"]["verify_peer"]);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Return the amount of cups of coffee had in the last 24 hours
|
|
||||||
function get_coffee_24h(): int {
|
|
||||||
// Retreive coffee list from endpoint
|
|
||||||
$resp = api_client()->call("/coffee", Method::GET);
|
|
||||||
|
|
||||||
$offset = 86400; // 24 hours in seconds
|
|
||||||
$now = time();
|
|
||||||
|
|
||||||
// Get only timestamps from response
|
|
||||||
$coffee_dates = array_column($resp[1], "date_timestamp_created");
|
|
||||||
// Filter array for timestamps between now and $offset
|
|
||||||
$coffee_last_day = array_filter($coffee_dates, fn(int $time): bool => $time >= ($now - $offset));
|
|
||||||
|
|
||||||
return count($coffee_last_day);
|
|
||||||
}
|
|
||||||
|
|
||||||
?>
|
|
||||||
<style><?= VV::css("pages/about") ?></style>
|
<style><?= VV::css("pages/about") ?></style>
|
||||||
<section class="intro">
|
<section class="intro">
|
||||||
<h2 aria-hidden="true">Hi, I'm</h2>
|
<h2 aria-hidden="true">Hi, I'm</h2>
|
||||||
|
|
|
@ -1,18 +1,26 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
use Reflect\Client;
|
use VLW\API\Client;
|
||||||
use Reflect\Method;
|
use VLW\API\Endpoints;
|
||||||
|
|
||||||
|
enum ContactFieldsEnum: string {
|
||||||
|
case EMAIL = "email";
|
||||||
|
case MESSAGE = "message";
|
||||||
|
}
|
||||||
|
|
||||||
// Connect to VLW API
|
// Connect to VLW API
|
||||||
$api = new Client($_ENV["api"]["base_url"], $_ENV["api"]["api_key"], https_peer_verify: $_ENV["api"]["verify_peer"]);
|
$api = new Client();
|
||||||
|
|
||||||
|
// Null when nothing has been sent, true if message has been sent, false if it failed
|
||||||
$message_sent = null;
|
$message_sent = null;
|
||||||
|
|
||||||
|
// Message has been submitted
|
||||||
if ($_SERVER["REQUEST_METHOD"] === "POST") {
|
if ($_SERVER["REQUEST_METHOD"] === "POST") {
|
||||||
$post_message = $api->call("messages", Method::POST, $_POST);
|
// Submit message to endpoint and set variable with results
|
||||||
|
$message_sent = $api->call(Endpoints::MESSAGES->value)->post([
|
||||||
// Set message sent to true if ok, false if something went wrong
|
ContactFieldsEnum::EMAIL->value => $_POST[ContactFieldsEnum::EMAIL->value],
|
||||||
$message_sent = $post_message[0] === 201;
|
ContactFieldsEnum::MESSAGE->value => $_POST[ContactFieldsEnum::MESSAGE->value]
|
||||||
|
])->ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
?>
|
?>
|
||||||
|
@ -63,11 +71,11 @@
|
||||||
<form method="POST">
|
<form method="POST">
|
||||||
<input-group>
|
<input-group>
|
||||||
<label>your email</label>
|
<label>your email</label>
|
||||||
<input type="email" name="email" placeholder="nissehult@example.com" autocomplete="off"></input>
|
<input type="email" name="<?= ContactFieldsEnum::EMAIL->value ?>" placeholder="nissehult@example.com" autocomplete="off"></input>
|
||||||
</input-group>
|
</input-group>
|
||||||
<input-group>
|
<input-group>
|
||||||
<label title="this field is required">your message<sup>*</sup></label>
|
<label title="this field is required">your message<sup>*</sup></label>
|
||||||
<textarea name="message" required placeholder="Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed molestie dignissim mauris vel dignissim. Sed et aliquet odio, id egestas libero. Vestibulum ut dui a turpis aliquam hendrerit id et dui. Morbi eu tristique quam, sit amet dictum felis. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin ac nibh a ex accumsan ullamcorper non quis eros. Nam at suscipit lacus. Nullam placerat semper sapien, vitae aliquet nisl elementum a. Duis viverra quam eros, eu vestibulum quam egestas sit amet. Duis lobortis varius malesuada. Mauris in fringilla mi. "></textarea>
|
<textarea name="<?= ContactFieldsEnum::MESSAGE->value ?>" required placeholder="Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed molestie dignissim mauris vel dignissim. Sed et aliquet odio, id egestas libero. Vestibulum ut dui a turpis aliquam hendrerit id et dui. Morbi eu tristique quam, sit amet dictum felis. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin ac nibh a ex accumsan ullamcorper non quis eros. Nam at suscipit lacus. Nullam placerat semper sapien, vitae aliquet nisl elementum a. Duis viverra quam eros, eu vestibulum quam egestas sit amet. Duis lobortis varius malesuada. Mauris in fringilla mi. "></textarea>
|
||||||
</input-group>
|
</input-group>
|
||||||
<button class="solid">send</button>
|
<button class="solid">send</button>
|
||||||
</form>
|
</form>
|
||||||
|
|
134
pages/search.php
134
pages/search.php
|
@ -1,26 +1,24 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
use Reflect\Client;
|
use VLW\API\Client;
|
||||||
use Reflect\Method;
|
use VLW\API\Endpoints;
|
||||||
|
|
||||||
|
$api = new Client();
|
||||||
|
|
||||||
// Connect to VLW API
|
$query = $_GET["q"] ?? null;
|
||||||
$api = new Client($_ENV["api"]["base_url"], $_ENV["api"]["api_key"], https_peer_verify: $_ENV["api"]["verify_peer"]);
|
|
||||||
|
|
||||||
// Get query string from search parameter if set
|
// Get search results from endpoint
|
||||||
$query = array_key_exists("q", $_GET) ? $_GET["q"] : null;
|
$response = $api->call(Endpoints::SEARCH->value)
|
||||||
|
// Get query string from search parameter if set
|
||||||
// Retreive rows from search endpoint if search parameter is set
|
->params(["q" => $query])
|
||||||
$resp = $query ? $api->call("/search?q={$query}", Method::GET) : null;
|
->get();
|
||||||
|
|
||||||
// ISO 8601: YYYY-MM-DD
|
|
||||||
$date_format = "Y-m-d";
|
|
||||||
|
|
||||||
?>
|
?>
|
||||||
<style><?= VV::css("pages/search") ?></style>
|
<style><?= VV::css("pages/search") ?></style>
|
||||||
<section class="search">
|
<section class="search">
|
||||||
<form method="GET">
|
<form method="GET">
|
||||||
<search>
|
<search>
|
||||||
<input name="q" type="text" placeholder="search anything..." value="<?= $_GET["q"] ?>"></input>
|
<input name="q" type="text" placeholder="search anything..." value="<?= $query ?>"></input>
|
||||||
</search>
|
</search>
|
||||||
<button type="submit" class="solid">Search</button>
|
<button type="submit" class="solid">Search</button>
|
||||||
</form>
|
</form>
|
||||||
|
@ -28,47 +26,83 @@
|
||||||
<button>advanced search options</button>
|
<button>advanced search options</button>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<?php if ($resp): ?>
|
<?php if ($response): ?>
|
||||||
<?php // Get response body ?>
|
<?php // Get response body ?>
|
||||||
<?php $body = $resp[1]; ?>
|
<?php $body = $response->json(); ?>
|
||||||
|
|
||||||
<?php // Get search results from API response if successful ?>
|
<?php // Do things depending on the response code from API ?>
|
||||||
<?php if ($resp[0] === 200): ?>
|
<?php switch ($response->code): default: ?>
|
||||||
|
<?php // An unknown error occured ?>
|
||||||
|
<section class="error">
|
||||||
|
<p>Something went wrong</p>
|
||||||
|
</section>
|
||||||
|
<?php break; ?>
|
||||||
|
|
||||||
<?php // Show category sections if search matches were found ?>
|
<?php // Query was successful! (Doesn't meant we got search results tho) ?>
|
||||||
<?php if ($body["total_num_results"] > 0): ?>
|
<?php case 200: ?>
|
||||||
<?php // Get search results by category ?>
|
|
||||||
<?php $categories = $body["results"]; ?>
|
|
||||||
|
|
||||||
<?php // Search response: Work ?>
|
<?php // Show category sections if search matches were found ?>
|
||||||
<?php if (!empty($categories["work"])): ?>
|
<?php if ($body["total_num_results"] > 0): ?>
|
||||||
<section class="title work">
|
<?php // Get search results by category ?>
|
||||||
<a href="/work" vv="search" vv-call="navigate"><h2>Work</h2></a>
|
<?php $categories = $body["results"]; ?>
|
||||||
<p><?= count($categories["work"]) ?> search result(s) from my public work</p>
|
|
||||||
</section>
|
<?php // Results category: work ?>
|
||||||
<section class="results work">
|
<?php if (!empty($categories["work"])): ?>
|
||||||
<?php foreach ($categories["work"] as $result): ?>
|
<section class="title work">
|
||||||
<a href="/work/<?= $result["id"] ?>" vv="search" vv-call="navigate"><div class="result">
|
<a href="/work" vv="search" vv-call="navigate"><h2>Work</h2></a>
|
||||||
<h3><?= $result["title"] ?></h3>
|
<p><?= count($categories["work"]) ?> search result(s) from my public work</p>
|
||||||
<p><?= $result["summary"] ?></p>
|
</section>
|
||||||
<p><?= date($date_format, $result["date_timestamp_created"]) ?></p>
|
<section class="results work">
|
||||||
</div></a>
|
|
||||||
<?php endforeach; ?>
|
<?php // List all work category search results ?>
|
||||||
|
<?php foreach ($categories["work"] as $result): ?>
|
||||||
|
<div class="result">
|
||||||
|
<h3><?= $result["title"] ?></h3>
|
||||||
|
<p><?= $result["summary"] ?></p>
|
||||||
|
<p><?= date(Client::DATE_FORMAT, $result["date_timestamp_created"]) ?></p>
|
||||||
|
|
||||||
|
<?php // Result has actions defined ?>
|
||||||
|
<?php if (!empty($result["actions"])): ?>
|
||||||
|
<div class="actions">
|
||||||
|
|
||||||
|
<?php // List all actions ?>
|
||||||
|
<?php foreach ($result["actions"] as $action): ?>
|
||||||
|
|
||||||
|
<?php if (!$action["external"]): ?>
|
||||||
|
<a href="<?= $action["href"] ?>" vv="search" vv-call="navigate"><button class="<?= $action["class_list"] ?>"><?= $action["display_text"] ?></button></a>
|
||||||
|
<?php else: ?>
|
||||||
|
<a href="<?= $action["href"] ?>" target="_blank"><button class="<?= $action["class_list"] ?>"><?= $action["display_text"] ?></button></a>
|
||||||
|
<?php endif; ?>
|
||||||
|
|
||||||
|
<?php endforeach; ?>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<?php endif; ?>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<?php endforeach; ?>
|
||||||
|
|
||||||
|
</section>
|
||||||
|
<?php endif; ?>
|
||||||
|
|
||||||
|
<?php // No search matches were found ?>
|
||||||
|
<?php else: ?>
|
||||||
|
<section class="empty">
|
||||||
|
<p>No results for search term "<?= $_GET["q"] ?>"</p>
|
||||||
</section>
|
</section>
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
|
|
||||||
<?php // No search matches were found ?>
|
<?php break; ?>
|
||||||
<?php else: ?>
|
|
||||||
<section class="empty">
|
<?php // No access to the search endpoint ?>
|
||||||
<p>No results for search term "<?= $_GET["q"] ?>"</p>
|
<?php case 404: ?>
|
||||||
|
<section class="error">
|
||||||
|
<p>Connection to VLW API was successful but lacking permission to search</p>
|
||||||
</section>
|
</section>
|
||||||
<?php endif; ?>
|
<?php break; ?>
|
||||||
|
|
||||||
<?php // Didn't get a 200 response from endpoint ?>
|
<?php // Got a request validation error from the endpoint ?>
|
||||||
<?php else: ?>
|
<?php case 422: ?>
|
||||||
|
|
||||||
<?php // Request validation issue if response code is 422 ?>
|
|
||||||
<?php if ($resp[0] === 422): ?>
|
|
||||||
|
|
||||||
<?php // Get all validation errors for query and list them ?>
|
<?php // Get all validation errors for query and list them ?>
|
||||||
<?php foreach ($body["GET"]["q"] as $error_code => $error_msg): ?>
|
<?php foreach ($body["GET"]["q"] as $error_code => $error_msg): ?>
|
||||||
|
@ -91,13 +125,9 @@
|
||||||
|
|
||||||
<?php endforeach; ?>
|
<?php endforeach; ?>
|
||||||
|
|
||||||
<?php // Something unexpected went wrong ?>
|
<?php break; ?>
|
||||||
<?php else: ?>
|
|
||||||
<section class="error">
|
<?php endswitch; ?>
|
||||||
<p>Something went wrong</p>
|
|
||||||
</section>
|
|
||||||
<?php endif; ?>
|
|
||||||
<?php endif; ?>
|
|
||||||
|
|
||||||
<?php // No query search paramter set, show general information ?>
|
<?php // No query search paramter set, show general information ?>
|
||||||
<?php else: ?>
|
<?php else: ?>
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
use Reflect\Client;
|
use VLW\API\Client;
|
||||||
use Reflect\Method;
|
use VLW\API\Endpoints;
|
||||||
|
|
||||||
// Connect to VLW API
|
// Connect to VLW API
|
||||||
$api = new Client($_ENV["api"]["base_url"], $_ENV["api"]["api_key"], https_peer_verify: $_ENV["api"]["verify_peer"]);
|
$api = new Client();
|
||||||
|
|
||||||
// Retreive rows from work endpoint
|
// Retreive rows from work endpoint
|
||||||
$resp = $api->call("/work", Method::GET);
|
$response = $api->call(Endpoints::WORK->value)->get();
|
||||||
|
|
||||||
?>
|
?>
|
||||||
<style><?= VV::css("pages/work") ?></style>
|
<style><?= VV::css("pages/work") ?></style>
|
||||||
|
@ -21,7 +21,7 @@
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<?php if ($resp[0] === 200): ?>
|
<?php if ($response->ok): ?>
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -32,7 +32,7 @@
|
||||||
|
|
||||||
$rows = [];
|
$rows = [];
|
||||||
// Create array of arrays ordered by decending year, month, day, items
|
// Create array of arrays ordered by decending year, month, day, items
|
||||||
foreach ($resp[1] as $row) {
|
foreach ($response->json() as $row) {
|
||||||
// Create array for current year if it doesn't exist
|
// Create array for current year if it doesn't exist
|
||||||
if (!array_key_exists($row["date_year"], $rows)) {
|
if (!array_key_exists($row["date_year"], $rows)) {
|
||||||
$rows[$row["date_year"]] = [];
|
$rows[$row["date_year"]] = [];
|
||||||
|
|
20
src/packages/API/composer.json
Normal file
20
src/packages/API/composer.json
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
{
|
||||||
|
"name": "local/api.client",
|
||||||
|
"description": "Wrapper for vlw.se API",
|
||||||
|
"type": "library",
|
||||||
|
"version": "1.0.0-dev",
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Victor Westerlund",
|
||||||
|
"email": "victor@vlw.se"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"VLW\\API\\": "src/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"reflect/client": "^3.0"
|
||||||
|
}
|
||||||
|
}
|
58
src/packages/API/composer.lock
generated
Normal file
58
src/packages/API/composer.lock
generated
Normal file
|
@ -0,0 +1,58 @@
|
||||||
|
{
|
||||||
|
"_readme": [
|
||||||
|
"This file locks the dependencies of your project to a known state",
|
||||||
|
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||||
|
"This file is @generated automatically"
|
||||||
|
],
|
||||||
|
"content-hash": "ea73f1cfa968f06be9c2ac54d2a56c96",
|
||||||
|
"packages": [
|
||||||
|
{
|
||||||
|
"name": "reflect/client",
|
||||||
|
"version": "dev-feat/responseobj",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/VictorWesterlund/reflect-client-php.git",
|
||||||
|
"reference": "228b3c665d4af5023ac4ed71fe32bb144521b43b"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/VictorWesterlund/reflect-client-php/zipball/228b3c665d4af5023ac4ed71fe32bb144521b43b",
|
||||||
|
"reference": "228b3c665d4af5023ac4ed71fe32bb144521b43b",
|
||||||
|
"shasum": ""
|
||||||
|
},
|
||||||
|
"type": "library",
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"Reflect\\": "src/Reflect/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"GPL-2.0-only"
|
||||||
|
],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Victor Westerlund",
|
||||||
|
"email": "victor.vesterlund@gmail.com"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "Extendable PHP interface for communicating with Reflect API over HTTP or UNIX sockets",
|
||||||
|
"support": {
|
||||||
|
"issues": "https://github.com/VictorWesterlund/reflect-client-php/issues",
|
||||||
|
"source": "https://github.com/VictorWesterlund/reflect-client-php/tree/feat/responseobj"
|
||||||
|
},
|
||||||
|
"time": "2024-03-18T11:57:57+00:00"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"packages-dev": [],
|
||||||
|
"aliases": [],
|
||||||
|
"minimum-stability": "stable",
|
||||||
|
"stability-flags": {
|
||||||
|
"reflect/client": 20
|
||||||
|
},
|
||||||
|
"prefer-stable": false,
|
||||||
|
"prefer-lowest": false,
|
||||||
|
"platform": [],
|
||||||
|
"platform-dev": [],
|
||||||
|
"plugin-api-version": "2.0.0"
|
||||||
|
}
|
18
src/packages/API/src/Client.php
Normal file
18
src/packages/API/src/Client.php
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace VLW\API;
|
||||||
|
|
||||||
|
use Reflect\Client as ReflectClient;
|
||||||
|
|
||||||
|
class Client extends ReflectClient {
|
||||||
|
// ISO 8601: YYYY-MM-DD
|
||||||
|
public const DATE_FORMAT = "Y-m-d";
|
||||||
|
|
||||||
|
public function __construct() {
|
||||||
|
parent::__construct(
|
||||||
|
$_ENV["api"]["base_url"],
|
||||||
|
$_ENV["api"]["api_key"],
|
||||||
|
$_ENV["api"]["verify_peer"]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Add table
Reference in a new issue