From 773fae62c1ee8b0e7fcabc0c178ec92c6d424598 Mon Sep 17 00:00:00 2001 From: Victor Westerlund Date: Sun, 16 Jun 2024 14:56:52 +0200 Subject: [PATCH] wip: 2024-06-16T13:05:34+0200 (1718535934) --- api/composer.json | 12 +- api/composer.lock | 71 +++++--- api/endpoints/messages/POST.php | 5 +- api/endpoints/search/GET.php | 116 ++---------- api/endpoints/work/GET.php | 26 ++- api/endpoints/work/actions/GET.php | 2 +- api/endpoints/work/tags/GET.php | 11 +- api/src/Endpoints.php | 8 +- .../databases/models/Messages/Messages.php | 14 +- composer.json | 16 +- composer.lock | 100 +++++------ pages/contact.php | 24 +-- pages/search.php | 170 +++++++----------- pages/work.php | 109 ++++++----- .../API/src/Client.php => client/API.php} | 7 +- src/entities/Entity.php | 57 ++++++ src/entities/VLW/Work.php | 74 ++++++++ src/packages/API/composer.json | 20 --- src/packages/API/composer.lock | 58 ------ 19 files changed, 429 insertions(+), 471 deletions(-) rename src/{packages/API/src/Client.php => client/API.php} (70%) create mode 100644 src/entities/Entity.php create mode 100644 src/entities/VLW/Work.php delete mode 100644 src/packages/API/composer.json delete mode 100644 src/packages/API/composer.lock diff --git a/api/composer.json b/api/composer.json index 4e00ddc..e1058f7 100755 --- a/api/composer.json +++ b/api/composer.json @@ -1,14 +1,8 @@ { "require": { - "local/api.endpoints": "1.0.0-dev", "reflect/plugin-rules": "^1.5", - "victorwesterlund/xenum": "^1.1" + "victorwesterlund/xenum": "dev-master", + "victorwesterlund/libmysqldriver": "dev-master" }, - "minimum-stability": "dev", - "repositories": [ - { - "type": "path", - "url": "src/packages/Endpoints" - } - ] + "minimum-stability": "dev" } diff --git a/api/composer.lock b/api/composer.lock index aaeccbf..2b6ee6b 100755 --- a/api/composer.lock +++ b/api/composer.lock @@ -4,33 +4,8 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "9da96ba90ef20d885034442b30dce0a3", + "content-hash": "13ba5cc60bab24ac8ef5b1018fe4249b", "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", @@ -68,9 +43,47 @@ }, "time": "2024-01-17T11:07:44+00:00" }, + { + "name": "victorwesterlund/libmysqldriver", + "version": "dev-master", + "source": { + "type": "git", + "url": "https://github.com/VictorWesterlund/php-libmysqldriver.git", + "reference": "adc2fda90a3b8308e8a9df202d5ec418a9220ff8" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/VictorWesterlund/php-libmysqldriver/zipball/adc2fda90a3b8308e8a9df202d5ec418a9220ff8", + "reference": "adc2fda90a3b8308e8a9df202d5ec418a9220ff8", + "shasum": "" + }, + "default-branch": true, + "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.6.1" + }, + "time": "2024-04-29T08:17:12+00:00" + }, { "name": "victorwesterlund/xenum", - "version": "1.1.1", + "version": "dev-master", "source": { "type": "git", "url": "https://github.com/VictorWesterlund/php-xenum.git", @@ -82,6 +95,7 @@ "reference": "8972f06f42abd1f382807a67e937d5564bb89699", "shasum": "" }, + "default-branch": true, "type": "library", "autoload": { "psr-4": { @@ -110,7 +124,8 @@ "aliases": [], "minimum-stability": "dev", "stability-flags": { - "local/api.endpoints": 20 + "victorwesterlund/xenum": 20, + "victorwesterlund/libmysqldriver": 20 }, "prefer-stable": false, "prefer-lowest": false, diff --git a/api/endpoints/messages/POST.php b/api/endpoints/messages/POST.php index 571493a..5e52b17 100755 --- a/api/endpoints/messages/POST.php +++ b/api/endpoints/messages/POST.php @@ -16,7 +16,6 @@ protected Ruleset $ruleset; public function __construct() { - parent::__construct(); $this->ruleset = new Ruleset(strict: true); $this->ruleset->POST([ @@ -31,6 +30,8 @@ ->min(1) ->max(parent::MYSQL_TEXT_MAX_LENGTH) ]); + + parent::__construct($this->ruleset); } public function main(): Response { @@ -40,7 +41,7 @@ $entity[MessagesModel::ID->value] = parent::gen_uuid4(); $entity[MessagesModel::DATE_CREATED->value] = time(); - return $this->db->for(MessagesModel::TABLE)->insert($_POST) === true + return $this->db->for(MessagesModel::TABLE)->insert($entity) === true ? new Response($entity[MessagesModel::ID->value], 201) : new Response("Failed to create message", 500); } diff --git a/api/endpoints/search/GET.php b/api/endpoints/search/GET.php index 3a39896..5c2c895 100755 --- a/api/endpoints/search/GET.php +++ b/api/endpoints/search/GET.php @@ -11,11 +11,10 @@ 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/Endpoints.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/WorkActions.php"); + require_once Path::root("src/databases/models/Work/Work.php"); class GET_Search extends VLWdb { const GET_QUERY = "q"; @@ -23,118 +22,35 @@ protected Ruleset $ruleset; public function __construct() { - parent::__construct(); $this->ruleset = new Ruleset(strict: true); $this->ruleset->GET([ (new Rules(self::GET_QUERY)) ->required() ->type(Type::STRING) - ->min(2) + ->min(1) ->max(parent::MYSQL_VARCHAR_MAX_LENGTH) ]); + + parent::__construct($this->ruleset); } - // Return an SQL string from array for use in prepared statements - private static function array_to_wildcard_sql(array $columns): string { - $sql = array_map(fn(string $column): string => "{$column} LIKE CONCAT('%', ?, '%')", $columns); - - return implode(" OR ", $sql); - } - - // Return chained AND statements from array for use in prepared statements - private static function array_to_and_statement(array $keys): string { - $sql = array_map(fn(string $k): string => "{$k} = ?", $keys); - - return implode(" AND ", $sql); - } - - // Wildcard search columns in table with query string from query string - // This has to be implemented manually until "libmysqldriver/MySQL" supports wildcard SELECT - private function search(string $table, array $columns, array $conditions = null): array { - // Create CSV from columns array - $columns_concat = implode(",", $columns); - - // Create SQL LIKE wildcard statement for each column. - $where = self::array_to_wildcard_sql($columns); - - // Create array of values from query string for each colum - $values = array_fill(0, count($columns), $_GET[self::GET_QUERY]); - - if ($conditions) { - $conditions_sql = self::array_to_and_statement(array_keys($conditions)); - - // Wrap positive where statements and prepare new group of conditions - // WHERE () AND () - $where = "({$where}) AND ({$conditions_sql})"; - - // Append values from conditions statements to prepared statement - array_push($values, ...array_values($conditions)); - } - - // Order the rows by the array index of $colums received - $rows = $this->db->exec("SELECT {$columns_concat} FROM {$table} WHERE {$where} ORDER BY {$columns_concat}", $values); - // Return results as assoc or empty array - return parent::is_mysqli_result($rows) ? $rows->fetch_all(MYSQLI_ASSOC) : []; - } - - // Search work table - private function search_work(): array { - $search = [ - WorkModel::TITLE->value, - WorkModel::SUMMARY->value, - WorkModel::DATE_TIMESTAMP_CREATED->value, - WorkModel::ID->value - ]; - - $conditions = [ - WorkModel::IS_LISTABLE->value => true - ]; - - $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 - - // 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); + private function search_work(): Response { + return (new Call(Endpoints::WORK->value))->params([ + WorkModel::TITLE->value => $_GET[self::GET_QUERY], + WorkModel::SUMMARY->value => $_GET[self::GET_QUERY] + ])->get(); } public function main(): Response { - // Bail out if request validation failed - if (!$this->ruleset->is_valid()) { - return $this->resp_rules_invalid(); - } - - // Get search results for each category - $categories = [ - WorkModel::TABLE => $this->search_work() + $results = [ + Endpoints::WORK->value => $this->search_work()->output() ]; - // Count total number of results from all categories - $total_num_results = 0; - foreach (array_values($categories) as $results) { - $total_num_results += count($results); - } + // Calculate the total number of results from all searched endpoints + $num_results = array_sum(array_map(fn(array $result): int => count($result), array_values($results))); - return new Response([ - "query" => $_GET[self::GET_QUERY], - "results" => $categories, - "total_num_results" => $total_num_results - ]); + // Return 404 if no search results + return new Response($results, $num_results > 0 ? 200 : 404); } } \ No newline at end of file diff --git a/api/endpoints/work/GET.php b/api/endpoints/work/GET.php index 14b289b..457977e 100755 --- a/api/endpoints/work/GET.php +++ b/api/endpoints/work/GET.php @@ -10,7 +10,7 @@ use VLW\API\Databases\VLWdb\Models\Work\WorkModel; 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/Work.php"); class GET_Work extends VLWdb { protected Ruleset $ruleset; @@ -26,12 +26,10 @@ (new Rules(WorkModel::TITLE->value)) ->type(Type::STRING) - ->min(3) ->max(parent::MYSQL_VARCHAR_MAX_LENGTH), (new Rules(WorkModel::SUMMARY->value)) ->type(Type::STRING) - ->min(1) ->max(parent::MYSQL_TEXT_MAX_LENGTH), (new Rules(WorkModel::IS_LISTABLE->value)) @@ -57,14 +55,34 @@ } public function main(): Response { + // Use copy of search paramters as filters + $filters = $_GET; + + // Do a wildcard search on the title column if provided + if (array_key_exists(WorkModel::TITLE->value, $_GET)) { + $filters[WorkModel::TITLE->value] = [ + "LIKE" => "%{$_GET[WorkModel::TITLE->value]}%" + ]; + } + + // Do a wildcard search on the summary column if provided + if (array_key_exists(WorkModel::SUMMARY->value, $_GET)) { + $filters[WorkModel::SUMMARY->value] = [ + "LIKE" => "%{$_GET[WorkModel::SUMMARY->value]}%" + ]; + } + $response = $this->db->for(WorkModel::TABLE) - ->where($_GET) + ->where($filters) ->select([ WorkModel::ID->value, WorkModel::TITLE->value, WorkModel::SUMMARY->value, WorkModel::IS_LISTABLE->value, WorkModel::IS_READABLE->value, + WorkModel::DATE_YEAR->value, + WorkModel::DATE_MONTH->value, + WorkModel::DATE_DAY->value, WorkModel::DATE_MODIFIED->value, WorkModel::DATE_CREATED->value ]); diff --git a/api/endpoints/work/actions/GET.php b/api/endpoints/work/actions/GET.php index 6694c92..ccbdb69 100644 --- a/api/endpoints/work/actions/GET.php +++ b/api/endpoints/work/actions/GET.php @@ -10,7 +10,7 @@ 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"); + require_once Path::root("src/databases/models/Work/WorkActions.php"); class GET_WorkActions extends VLWdb { protected Ruleset $ruleset; diff --git a/api/endpoints/work/tags/GET.php b/api/endpoints/work/tags/GET.php index 33ae111..7b6841b 100644 --- a/api/endpoints/work/tags/GET.php +++ b/api/endpoints/work/tags/GET.php @@ -7,7 +7,10 @@ use ReflectRules\Ruleset; use VLW\API\Databases\VLWdb\VLWdb; - use VLW\API\Databases\VLWdb\Models\Work\WorkTagsModel; + use VLW\API\Databases\VLWdb\Models\Work\{ + WorkTagsModel, + WorkTagsNameEnum + }; require_once Path::root("src/databases/VLWdb.php"); require_once Path::root("src/databases/models/Work/WorkTags.php"); @@ -31,11 +34,11 @@ } public function main(): Response { - $response = $this->db->for(FieldsEnumsModel::TABLE) + $response = $this->db->for(WorkTagsModel::TABLE) ->where($_GET) ->select([ - FieldsEnumsModel::REF_WORK_ID->value, - FieldsEnumsModel::NAME->value + WorkTagsModel::REF_WORK_ID->value, + WorkTagsModel::NAME->value ]); return $response->num_rows > 0 diff --git a/api/src/Endpoints.php b/api/src/Endpoints.php index b049671..cb6bb87 100644 --- a/api/src/Endpoints.php +++ b/api/src/Endpoints.php @@ -7,5 +7,11 @@ // Enum of all available VLW endpoints grouped by category enum Endpoints: string { - case WORK = "/work"; + case SEARCH = "/search"; + + case MESSAGES = "/messages"; + + case WORK = "/work"; + case WORK_TAGS = "/work/tags"; + case WORK_ACTIONS = "/work/actions"; } \ No newline at end of file diff --git a/api/src/databases/models/Messages/Messages.php b/api/src/databases/models/Messages/Messages.php index f9c20fb..e43d8e4 100644 --- a/api/src/databases/models/Messages/Messages.php +++ b/api/src/databases/models/Messages/Messages.php @@ -5,11 +5,11 @@ enum MessagesModel: string { const TABLE = "messages"; - case ID = "id"; - case EMAIL = "email"; - case MESSAGE = "message"; - case IS_READ = "is_read"; - case IS_SPAM = "is_spam"; - case IS_SAVED = "is_saved"; - case DATE_TIMESTAMP_CREATED = "date_timestamp_created"; + case ID = "id"; + case EMAIL = "email"; + case MESSAGE = "message"; + case IS_READ = "is_read"; + case IS_SPAM = "is_spam"; + case IS_SAVED = "is_saved"; + case DATE_CREATED = "date_created"; } \ No newline at end of file diff --git a/composer.json b/composer.json index 7724816..284b861 100755 --- a/composer.json +++ b/composer.json @@ -1,17 +1,7 @@ { "require": { - "local/api.client": "1.0.0-dev", - "local/api.endpoints": "1.0.0-dev" + "reflect/client": "dev-master", + "victorwesterlund/xenum": "dev-master" }, - "minimum-stability": "dev", - "repositories": [ - { - "type": "path", - "url": "src/packages/API" - }, - { - "type": "path", - "url": "api/src/packages/Endpoints" - } - ] + "minimum-stability": "dev" } diff --git a/composer.lock b/composer.lock index 5e24289..1149916 100755 --- a/composer.lock +++ b/composer.lock @@ -4,64 +4,11 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "73a61bf0308871f9dc9ad050aedfe13e", + "content-hash": "2a8a06dc452a4eb9055d238f771dcd37", "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": "3.0.6", + "version": "dev-master", "source": { "type": "git", "url": "https://github.com/VictorWesterlund/reflect-client-php.git", @@ -73,6 +20,7 @@ "reference": "89a8c041044c8c60cefafc4716d5d61b96c43e06", "shasum": "" }, + "default-branch": true, "type": "library", "autoload": { "psr-4": { @@ -95,14 +43,52 @@ "source": "https://github.com/VictorWesterlund/reflect-client-php/tree/3.0.6" }, "time": "2024-04-06T14:55:04+00:00" + }, + { + "name": "victorwesterlund/xenum", + "version": "dev-master", + "source": { + "type": "git", + "url": "https://github.com/VictorWesterlund/php-xenum.git", + "reference": "8972f06f42abd1f382807a67e937d5564bb89699" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/VictorWesterlund/php-xenum/zipball/8972f06f42abd1f382807a67e937d5564bb89699", + "reference": "8972f06f42abd1f382807a67e937d5564bb89699", + "shasum": "" + }, + "default-branch": true, + "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": "PHP eXtended Enums. The missing quality-of-life features from PHP 8+ Enums", + "support": { + "issues": "https://github.com/VictorWesterlund/php-xenum/issues", + "source": "https://github.com/VictorWesterlund/php-xenum/tree/1.1.1" + }, + "time": "2023-11-20T10:10:39+00:00" } ], "packages-dev": [], "aliases": [], "minimum-stability": "dev", "stability-flags": { - "local/api.client": 20, - "local/api.endpoints": 20 + "reflect/client": 20, + "victorwesterlund/xenum": 20 }, "prefer-stable": false, "prefer-lowest": false, diff --git a/pages/contact.php b/pages/contact.php index aaeebf5..867c20e 100755 --- a/pages/contact.php +++ b/pages/contact.php @@ -1,15 +1,19 @@ @@ -50,8 +54,8 @@ // Send message via API $send = $api->call(Endpoints::MESSAGES->value)->post([ - ContactFieldsEnum::EMAIL->value => $_POST[ContactFieldsEnum::EMAIL->value], - ContactFieldsEnum::MESSAGE->value => $_POST[ContactFieldsEnum::MESSAGE->value] + MessagesModel::EMAIL->value => $_POST[MessagesModel::EMAIL->value], + MessagesModel::MESSAGE->value => $_POST[MessagesModel::MESSAGE->value] ]); ?> @@ -74,11 +78,11 @@
- + - +
diff --git a/pages/search.php b/pages/search.php index 068d8a5..78c9b79 100755 --- a/pages/search.php +++ b/pages/search.php @@ -1,24 +1,32 @@ call(Endpoints::SEARCH->value) - // Get query string from search parameter if set - ->params(["q" => $query]) - ->get(); + $response = $api->call(Endpoints::SEARCH->value)->params([SEARCH_PARAM => $_GET[SEARCH_PARAM]])->get(); ?> - +ok): ?> - json(); ?> + json(); ?> - - code): default: ?> - -
-

Something went wrong

-
- + + value]): ?> +
+

Work

+

value]) ?> search result(s) from my public work

+
+
- - + + value] as $result): ?> +
+

value] ?>

+

value] ?>

+

value]) ?>

- - 0): ?> - - + + +
- - -
-

Work

-

search result(s) from my public work

-
-
- - - - - - -
- - - - -
- -

No results for search term ""

-
- - - - - - -
-

Connection to VLW API was successful but lacking permission to search

-
- - - - - - - $error_msg): ?> - - - -
-

Unknown request validation error

-
- - - - -
- -

type at least characters to search!

-
- - - + +
+ +
- - - - - - +
+ - + + +
+ +

No results for search term ""

+
+ +
+ +

Start typing to search

+
+ + \ No newline at end of file diff --git a/pages/work.php b/pages/work.php index c8c6930..7b5bdd1 100755 --- a/pages/work.php +++ b/pages/work.php @@ -1,13 +1,32 @@ call(Endpoints::WORK->value)->get(); + require_once Path::root("src/client/API.php"); + require_once Path::root("api/src/Endpoints.php"); + + require_once Path::root("api/src/databases/models/Work/Work.php"); + require_once Path::root("api/src/databases/models/Work/WorkTags.php"); + require_once Path::root("api/src/databases/models/Work/WorkActions.php"); + + // Connect to VLW API + $api = new API(); + + // Retreive rows from work endpoints + $resp_work = $api->call(Endpoints::WORK->value)->get(); + + // Resolve tags and actions if we got work results + if ($resp_work->ok) { + $work_tags = $api->call(Endpoints::WORK_TAGS->value)->get()->json(); + $work_actions = $api->call(Endpoints::WORK_ACTIONS->value)->get()->json(); + } ?> @@ -21,7 +40,7 @@ -ok): ?> +ok): ?> json() as $row) { + foreach ($resp_work->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"]] = []; + if (!array_key_exists($row[WorkModel::DATE_YEAR->value], $rows)) { + $rows[$row[WorkModel::DATE_YEAR->value]] = []; } // Create array for current month if it doesn't exist - if (!array_key_exists($row["date_month"], $rows[$row["date_year"]])) { - $rows[$row["date_year"]][$row["date_month"]] = []; + if (!array_key_exists($row[WorkModel::DATE_MONTH->value], $rows[$row[WorkModel::DATE_YEAR->value]])) { + $rows[$row[WorkModel::DATE_YEAR->value]][$row[WorkModel::DATE_MONTH->value]] = []; } // Create array for current day if it doesn't exist - if (!array_key_exists($row["date_day"], $rows[$row["date_year"]][$row["date_month"]])) { - $rows[$row["date_year"]][$row["date_month"]][$row["date_day"]] = []; + if (!array_key_exists($row[WorkModel::DATE_DAY->value], $rows[$row[WorkModel::DATE_YEAR->value]][$row[WorkModel::DATE_MONTH->value]])) { + $rows[$row[WorkModel::DATE_YEAR->value]][$row[WorkModel::DATE_MONTH->value]][$row[WorkModel::DATE_DAY->value]] = []; } // Append item to ordered array - $rows[$row["date_year"]][$row["date_month"]][$row["date_day"]][] = $row; + $rows[$row[WorkModel::DATE_YEAR->value]][$row[WorkModel::DATE_MONTH->value]][$row[WorkModel::DATE_DAY->value]][] = $row; } ?> @@ -84,52 +103,50 @@
- - + + value), $item[WorkModel::ID->value]); ?> + + +
- -

">

+ + + + +

value] ?>

- -

+ value])): ?> +

value] ?>

- - - +

value] ?>

- - - - - - ." type=""> - - - - ." type="" loading="lazy"/> -
- - -

+ + value), $item[WorkModel::ID->value]); ?> - +
- + value] + // Bind VV Interactions for local links + ? "vv='work' vv-call='navigate'" + // Open external links in a new tab + : "target='_blank'"; + + $link_href = $action[WorkActionsModel::HREF->value] === null + // Navigate to work details page if no href is defined + ? "/work/{$item[WorkModel::ID->value]}" + // Href is defined so use it directly + : $action[WorkActionsModel::HREF->value]; ?> > diff --git a/src/packages/API/src/Client.php b/src/client/API.php similarity index 70% rename from src/packages/API/src/Client.php rename to src/client/API.php index 2f5dd7d..471975d 100644 --- a/src/packages/API/src/Client.php +++ b/src/client/API.php @@ -1,10 +1,11 @@ id = $id; + $this->api = new Api(); + $this->endpoint = $endpoint; + + $this->resolve_entity_by_id(); + } + + private function resolve_entity_by_id() { + // Bail out wit a dummy Response if no id was provided + if (!$this->id) { + $this->response = new Response("", 404); + return; + } + + $this->response = $this->api + ->call($this->endpoint->value) + ->params([self::ENTITY_ID => $this->id]) + ->get(); + + // Load response into entity object if successful + if ($this->response->ok) { + $this->entity = (object) $this->response->json()[0]; + } + } + + public function resolve(Endpoints $endpoint, array $params): array { + $response = $this->api->call($endpoint->value)->params($params)->get(); + + return $response->ok ? $response->json() : []; + } + } \ No newline at end of file diff --git a/src/entities/VLW/Work.php b/src/entities/VLW/Work.php new file mode 100644 index 0000000..5b4b26a --- /dev/null +++ b/src/entities/VLW/Work.php @@ -0,0 +1,74 @@ +signatures) { + return $this->signatures; + } + + foreach ($this->resolve(Endpoints::ICELDB_ANALYSES_SIGNATURES, ["ref_analysis_id" => $this->id]) as $rel) { + $this->signatures[$rel["id"]] = $rel; + $this->signatures[$rel["id"]]["user"] = $this->resolve(Endpoints::ICELDB_USERS, ["ref_user_id" => $rel["ref_user_id"]])[0]; + } + + return $this->signatures; + } + + public function documents(): array { + if ($this->documents) { + return $this->documents; + } + + $this->documents = $this->resolve(Endpoints::ICELDB_ANALYSES_DOCUMENTS, ["ref_analysis_id" => $this->id]); + return $this->documents; + } + + public function studies(): array { + if ($this->studies) { + return $this->studies; + } + + foreach ($this->resolve(Endpoints::ICELDB_STUDIES_ANALYSES, ["ref_analysis_id" => $this->id]) as $rel) { + $this->studies[] = $this->resolve(Endpoints::ICELDB_STUDIES, ["id" => $rel["ref_study_id"]]); + } + + return $this->studies; + } + + public function notes(): array { + if ($this->notes) { + return $this->notes; + } + + $this->notes = $this->resolve(Endpoints::ICELDB_ANALYSES_NOTES, ["ref_analysis_id" => $this->id]); + return $this->notes; + } + + public function individuals(): array { + if ($this->individuals) { + return $this->individuals; + } + + foreach ($this->resolve(Endpoints::ICELDB_ANALYSES_INDIVIDUALS, ["ref_analysis_id" => $this->id]) as $rel) { + $this->individuals[] = $this->resolve(Endpoints::ICELDB_INDIVIDUALS, ["id" => $rel["ref_individual_id"]])[0]; + } + + return $this->individuals; + } + } \ No newline at end of file diff --git a/src/packages/API/composer.json b/src/packages/API/composer.json deleted file mode 100644 index 2edfca6..0000000 --- a/src/packages/API/composer.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "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" - } -} diff --git a/src/packages/API/composer.lock b/src/packages/API/composer.lock deleted file mode 100644 index 2896728..0000000 --- a/src/packages/API/composer.lock +++ /dev/null @@ -1,58 +0,0 @@ -{ - "_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" -}