feat: major post-launch fixes and bump of reflect/client to 3.0.6 (#9)

This commit is contained in:
Victor Westerlund 2024-04-06 22:45:33 +00:00 committed by GitHub
parent 140132fa72
commit 150559b075
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
22 changed files with 471 additions and 264 deletions

View file

@ -1,7 +1,14 @@
{
"require": {
"local/api.endpoints": "1.0.0-dev",
"reflect/plugin-rules": "^1.5",
"victorwesterlund/innodb-fk": "^1.0",
"victorwesterlund/xenum": "^1.1"
}
},
"minimum-stability": "dev",
"repositories": [
{
"type": "path",
"url": "src/packages/Endpoints"
}
]
}

111
api/composer.lock generated
View file

@ -4,8 +4,33 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "ba3fa8466aa20501e06050d722c86a35",
"content-hash": "9da96ba90ef20d885034442b30dce0a3",
"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",
"version": "1.5.0",
@ -43,84 +68,6 @@
},
"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",
"version": "1.1.1",
@ -161,8 +108,10 @@
],
"packages-dev": [],
"aliases": [],
"minimum-stability": "stable",
"stability-flags": [],
"minimum-stability": "dev",
"stability-flags": {
"local/api.endpoints": 20
},
"prefer-stable": false,
"prefer-lowest": false,
"platform": [],

View file

@ -1,17 +1,21 @@
<?php
use Reflect\Call;
use Reflect\Path;
use Reflect\Response;
use ReflectRules\Type;
use ReflectRules\Rules;
use ReflectRules\Ruleset;
use VLW\API\Endpoints;
use VLW\API\Databases\VLWdb\VLWdb;
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/models/Work.php");
require_once Path::root("src/databases/models/WorkActions.php");
class GET_Search extends VLWdb {
const GET_QUERY = "q";
@ -87,7 +91,15 @@
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

View file

@ -1,13 +1,14 @@
<?php
use Reflect\Call;
use Reflect\Path;
use Reflect\Method;
use Reflect\Response;
use ReflectRules\Type;
use ReflectRules\Rules;
use ReflectRules\Ruleset;
use Reflect\Method;
use function Reflect\Call;
use VLW\API\Endpoints;
use VLW\API\Databases\VLWdb\VLWdb;
use VLW\API\Databases\VLWdb\Models\Work\WorkModel;
@ -45,19 +46,6 @@
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
// Return 422 Unprocessable Content error if request validation failed
@ -134,13 +122,11 @@
$rows = [];
while ($row = $resp->fetch_assoc()) {
$row["tags"] = $this->fetch_row_tags($row["id"]);
$row["actions"] = $this->fetch_row_actions($row["id"]);
// Resolve media entities in srcset
$srcset = Call("media/srcset?id={$row[WorkModel::COVER_SRCSET->value]}", Method::GET);
// Mutate key on current row
$row[WorkModel::COVER_SRCSET->value] = $srcset->ok ? $srcset->output() : [];
// Fetch actions for work entity by id from endpoint
$row["actions"] = (new Call(Endpoints::WORK_ACTIONS->value))
->params([WorkActionsModel::ANCHOR->value => $row[WorkModel::ID->value]])
->get()->output();
$rows[] = $row;
}

View 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([]);
}
}

View file

@ -5,6 +5,8 @@
use libmysqldriver\MySQL;
class VLWdb {
const UUID_LENGTH = 36;
const MYSQL_TEXT_MAX_LENGTH = 65538;
const MYSQL_VARCHAR_MAX_LENGTH = 255;
const MYSQL_INT_MAX_LENGHT = 2147483647;

View 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/"
}
}
}

View 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";
}

View file

@ -14,6 +14,7 @@
box-sizing: border-box;
font-family: "Roboto Mono", sans-serif;
color: inherit;
font-size: inherit;
}
::-webkit-scrollbar {
@ -29,6 +30,7 @@ body {
color: white;
overflow-x: hidden;
min-height: 100svh;
font-size: 15px;
}
body.search-dialog-open {
@ -53,10 +55,22 @@ a {
text-decoration-color: var(--color-accent);
}
h1 {
font-size: 30px;
color: var(--color-accent);
}
h2 {
font-size: 30px;
}
h3 {
font-size: 25px;
}
/* ## Buttons */
button {
font-size: inherit;
padding: calc(var(--padding) / 2) var(--padding);
color: white;
border: solid 2px white;
@ -161,7 +175,7 @@ searchbox {
padding: var(--padding);
gap: var(--padding);
fill: var(--color-accent);
font-size: 14px;
font-size: 13px;
color: rgba(255, 255, 255, .5);
cursor: pointer;
}
@ -218,7 +232,7 @@ search input {
border: none;
outline: none;
color: black;
font-size: 18px;
font-size: 16px;
padding: var(--padding) calc(var(--padding) * 1.5);
background-color: rgba(255, 255, 255, .05);
box-shadow: 0 5px 70px 10px rgba(0, 0, 0, .3);

View file

@ -13,17 +13,6 @@ main {
/* # Sections */
/* ## Into */
section.intro h2 {
font-size: 25px;
}
section.intro h1 {
font-size: 40px;
color: var(--color-accent);
}
/* ## Divider */
main > hr {
@ -38,12 +27,8 @@ section.about {
gap: calc(var(--padding) / 2);
}
section.about {
font-size: 16px;
}
section.about p:first-of-type:first-letter {
font-size: 1.5rem;
font-size: 1.8rem;
font-weight: bold;
margin-right: .1rem;
color: var(--color-accent);
@ -73,7 +58,7 @@ div.interests {
height: 100%;
font-weight: bold;
pointer-events: none;
font-size: 60px;
font-size: 50px;
color: var(--color-accent);
overflow: hidden;
opacity: 0;

View file

@ -46,7 +46,6 @@ section.social social p {
transform: translate(0, 0);
background-color: rgba(var(--primer-color-accent), .1);
padding: 5px 10px;
font-size: 17px;
white-space: nowrap;
pointer-events: none;
border-radius: 6px;
@ -98,7 +97,6 @@ section.form :is(input, textarea) {
min-width: 100%;
max-width: 100%;
color: black;
font-size: 15px;
padding: var(--padding);
border-radius: 4px;
border: none;
@ -160,7 +158,6 @@ section.form-message h3 {
}
section.form-message pre {
font-size: 11px;
padding: var(--padding);
background-color: rgba(0, 0, 0, .15);
}

View file

@ -38,12 +38,24 @@ section.search button[type="submit"] {
max-width: 350px;
}
section.search > svg {
width: 100%;
}
body:not([vv-page="/search"]) section.search {
display: none;
}
/* # Search results */
section.results .result {
display: flex;
flex-direction: column;
gap: calc(var(--padding) / 2);
}
/* ---- */
main > svg,
dialog.search search search-results > svg {
margin: auto;
@ -57,7 +69,7 @@ dialog.search search search-results .empty {
/* ## Titles */
section.title h2 {
section.title a h2 {
color: var(--color-accent);
}
@ -76,19 +88,6 @@ section.results.work {
section.results.work .result {
padding: var(--padding);
background-color: rgba(255, 255, 255, .1);
background-color: rgba(255, 255, 255, .03);
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);
}
}

View file

@ -9,7 +9,6 @@ main {
display: flex;
flex-direction: column;
gap: var(--padding);
padding: calc(var(--padding) * 1.5);
width: 100%;
max-width: 1200px;
overflow-x: initial;
@ -114,18 +113,6 @@ section.timeline .items .item .tags .tag {
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 {
max-width: 100%;
height: 250px;
@ -133,7 +120,6 @@ section.timeline .items .item img {
section.timeline .items .item .actions {
margin-top: 7px;
font-size: 13px;
}
/* ## Note */
@ -174,7 +160,6 @@ section.note {
section.timeline .track {
position: relative;
left: calc(var(--padding) * 1.5);
background: unset;
z-index: 10;
pointer-events: none;
@ -194,6 +179,7 @@ section.note {
}
section.timeline .items .item {
padding: calc(var(--padding) * 1.5) 0;
width: calc(100vw - (var(--padding) * 3.5));
}

View file

@ -1,5 +1,17 @@
{
"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
View file

@ -4,20 +4,73 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "3e10269d358ba18734f4f011cd22c42e",
"content-hash": "73a61bf0308871f9dc9ad050aedfe13e",
"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",
"version": "2.1.4",
"version": "3.0.6",
"source": {
"type": "git",
"url": "https://github.com/VictorWesterlund/reflect-client-php.git",
"reference": "47cee961d1bfdd9261a58dde753d824947e91636"
"reference": "89a8c041044c8c60cefafc4716d5d61b96c43e06"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/VictorWesterlund/reflect-client-php/zipball/47cee961d1bfdd9261a58dde753d824947e91636",
"reference": "47cee961d1bfdd9261a58dde753d824947e91636",
"url": "https://api.github.com/repos/VictorWesterlund/reflect-client-php/zipball/89a8c041044c8c60cefafc4716d5d61b96c43e06",
"reference": "89a8c041044c8c60cefafc4716d5d61b96c43e06",
"shasum": ""
},
"type": "library",
@ -39,15 +92,18 @@
"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/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": [],
"aliases": [],
"minimum-stability": "stable",
"stability-flags": [],
"minimum-stability": "dev",
"stability-flags": {
"local/api.client": 20,
"local/api.endpoints": 20
},
"prefer-stable": false,
"prefer-lowest": false,
"platform": [],

View file

@ -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>
<section class="intro">
<h2 aria-hidden="true">Hi, I'm</h2>

View file

@ -1,18 +1,26 @@
<?php
use Reflect\Client;
use Reflect\Method;
use VLW\API\Client;
use VLW\API\Endpoints;
enum ContactFieldsEnum: string {
case EMAIL = "email";
case MESSAGE = "message";
}
// 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 has been submitted
if ($_SERVER["REQUEST_METHOD"] === "POST") {
$post_message = $api->call("messages", Method::POST, $_POST);
// Set message sent to true if ok, false if something went wrong
$message_sent = $post_message[0] === 201;
// Submit message to endpoint and set variable with results
$message_sent = $api->call(Endpoints::MESSAGES->value)->post([
ContactFieldsEnum::EMAIL->value => $_POST[ContactFieldsEnum::EMAIL->value],
ContactFieldsEnum::MESSAGE->value => $_POST[ContactFieldsEnum::MESSAGE->value]
])->ok;
}
?>
@ -63,11 +71,11 @@
<form method="POST">
<input-group>
<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>
<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>
<button class="solid">send</button>
</form>

View file

@ -1,26 +1,24 @@
<?php
use Reflect\Client;
use Reflect\Method;
use VLW\API\Client;
use VLW\API\Endpoints;
$api = new Client();
// Connect to VLW API
$api = new Client($_ENV["api"]["base_url"], $_ENV["api"]["api_key"], https_peer_verify: $_ENV["api"]["verify_peer"]);
$query = $_GET["q"] ?? null;
// Get query string from search parameter if set
$query = array_key_exists("q", $_GET) ? $_GET["q"] : null;
// Retreive rows from search endpoint if search parameter is set
$resp = $query ? $api->call("/search?q={$query}", Method::GET) : null;
// ISO 8601: YYYY-MM-DD
$date_format = "Y-m-d";
// Get search results from endpoint
$response = $api->call(Endpoints::SEARCH->value)
// Get query string from search parameter if set
->params(["q" => $query])
->get();
?>
<style><?= VV::css("pages/search") ?></style>
<section class="search">
<form method="GET">
<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>
<button type="submit" class="solid">Search</button>
</form>
@ -28,47 +26,83 @@
<button>advanced search options</button>
</section>
<?php if ($resp): ?>
<?php if ($response): ?>
<?php // Get response body ?>
<?php $body = $resp[1]; ?>
<?php $body = $response->json(); ?>
<?php // Get search results from API response if successful ?>
<?php if ($resp[0] === 200): ?>
<?php // Do things depending on the response code from API ?>
<?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 if ($body["total_num_results"] > 0): ?>
<?php // Get search results by category ?>
<?php $categories = $body["results"]; ?>
<?php // Query was successful! (Doesn't meant we got search results tho) ?>
<?php case 200: ?>
<?php // Search response: Work ?>
<?php if (!empty($categories["work"])): ?>
<section class="title work">
<a href="/work" vv="search" vv-call="navigate"><h2>Work</h2></a>
<p><?= count($categories["work"]) ?> search result(s) from my public work</p>
</section>
<section class="results work">
<?php foreach ($categories["work"] as $result): ?>
<a href="/work/<?= $result["id"] ?>" vv="search" vv-call="navigate"><div class="result">
<h3><?= $result["title"] ?></h3>
<p><?= $result["summary"] ?></p>
<p><?= date($date_format, $result["date_timestamp_created"]) ?></p>
</div></a>
<?php endforeach; ?>
<?php // Show category sections if search matches were found ?>
<?php if ($body["total_num_results"] > 0): ?>
<?php // Get search results by category ?>
<?php $categories = $body["results"]; ?>
<?php // Results category: work ?>
<?php if (!empty($categories["work"])): ?>
<section class="title work">
<a href="/work" vv="search" vv-call="navigate"><h2>Work</h2></a>
<p><?= count($categories["work"]) ?> search result(s) from my public work</p>
</section>
<section class="results work">
<?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>
<?php endif; ?>
<?php // No search matches were found ?>
<?php else: ?>
<section class="empty">
<p>No results for search term "<?= $_GET["q"] ?>"</p>
<?php break; ?>
<?php // No access to the search endpoint ?>
<?php case 404: ?>
<section class="error">
<p>Connection to VLW API was successful but lacking permission to search</p>
</section>
<?php endif; ?>
<?php break; ?>
<?php // Didn't get a 200 response from endpoint ?>
<?php else: ?>
<?php // Request validation issue if response code is 422 ?>
<?php if ($resp[0] === 422): ?>
<?php // Got a request validation error from the endpoint ?>
<?php case 422: ?>
<?php // Get all validation errors for query and list them ?>
<?php foreach ($body["GET"]["q"] as $error_code => $error_msg): ?>
@ -91,13 +125,9 @@
<?php endforeach; ?>
<?php // Something unexpected went wrong ?>
<?php else: ?>
<section class="error">
<p>Something went wrong</p>
</section>
<?php endif; ?>
<?php endif; ?>
<?php break; ?>
<?php endswitch; ?>
<?php // No query search paramter set, show general information ?>
<?php else: ?>

View file

@ -1,13 +1,13 @@
<?php
use Reflect\Client;
use Reflect\Method;
use VLW\API\Client;
use VLW\API\Endpoints;
// 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
$resp = $api->call("/work", Method::GET);
$response = $api->call(Endpoints::WORK->value)->get();
?>
<style><?= VV::css("pages/work") ?></style>
@ -21,7 +21,7 @@
</div>
</section>
<?php if ($resp[0] === 200): ?>
<?php if ($response->ok): ?>
<?php
/*
@ -32,7 +32,7 @@
$rows = [];
// 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
if (!array_key_exists($row["date_year"], $rows)) {
$rows[$row["date_year"]] = [];

View 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
View 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"
}

View 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"]
);
}
}