From c3f7cb78b180b45e460f939fc50db4cdf451f6ab Mon Sep 17 00:00:00 2001 From: Bojidar Marinov Date: Wed, 13 Sep 2017 17:37:11 +0300 Subject: [PATCH] Add Godot version field to assets and an undelete route Closes #100 --- .editorconfig | 7 +++++- data/migration-4.sql | 6 ++++++ src/Helpers/Utils.php | 35 ++++++++++++++++++++++++++++++ src/constants.php | 16 +++++++++++++- src/queries.php | 31 ++++++++++++++++++--------- src/routes/asset.php | 40 ++++++++++++++++++++++++++++++++++- src/routes/asset_edit.php | 7 ++++++ style/base.css | 24 +++++++++++++++++++++ templates/_asset_fields.phtml | 18 ++++++++++++++++ templates/_header.phtml | 1 + templates/asset.phtml | 1 + templates/asset_edit.phtml | 1 + templates/asset_edits.phtml | 1 + templates/assets.phtml | 15 +++++++++++++ 14 files changed, 190 insertions(+), 13 deletions(-) create mode 100644 data/migration-4.sql create mode 100644 style/base.css diff --git a/.editorconfig b/.editorconfig index 1ebd975..ccc4f0d 100644 --- a/.editorconfig +++ b/.editorconfig @@ -7,7 +7,12 @@ end_of_line = lf insert_final_newline = true charset = utf-8 +# CSS +[*.css] +indent_style = space +indent_size = 4 + # PHP -[*.php] +[*.{php,phtml}] indent_style = space indent_size = 4 diff --git a/data/migration-4.sql b/data/migration-4.sql new file mode 100644 index 0000000..e54298d --- /dev/null +++ b/data/migration-4.sql @@ -0,0 +1,6 @@ + +ALTER TABLE `as_assets` ADD `godot_version` INT(7) NOT NULL AFTER `category_id`, ADD INDEX `godot_version_index` (`godot_version`); +UPDATE `as_assets` SET `godot_version` = 20100 WHERE `godot_version` = 0; + +ALTER TABLE `as_asset_edits` ADD `godot_version` INT(7) NULL AFTER `category_id`, ADD INDEX `godot_version_index` (`godot_version`); +UPDATE `as_asset_edits` SET `godot_version` = 20100 WHERE `asset_id` = -1; diff --git a/src/Helpers/Utils.php b/src/Helpers/Utils.php index 53ecb81..ea73ad3 100644 --- a/src/Helpers/Utils.php +++ b/src/Helpers/Utils.php @@ -74,6 +74,41 @@ public function getDefaultIssuesUrl($repo_url, $provider) // i.e. browse_url, do } } + public function getFormattedGodotVersion($internal_id, &$warning=null) + { + if ($internal_id == 0) { + $warning = "Setting Godot version as \"unknown\" is not recommended, as it would prevent people from finding your asset easily."; + } + if (isset($this->c->constants['special_godot_versions'][$internal_id])) { + return $this->c->constants['special_godot_versions'][$internal_id]; + } else { + $major = floor($internal_id / 10000) % 100; + $minor = floor($internal_id / 100) % 100; + $patch = floor($internal_id / 1) % 100; + if ($patch != 0) { + return $major . '.' . $minor . '.' . $patch; + } else { + return $major . '.' . $minor; + } + } + } + + public function getUnformattedGodotVersion($value) + { + if (is_int($value)) { + return $value; + } + if (isset($this->c->constants['special_godot_versions'][$value])) { + return $this->c->constants['special_godot_versions'][$value]; + } else { + $slices = explode('.', $value); + $major = (int) $slices[0]; + $minor = min(100, max(0, (int) ($slices[1] ?? 0))); + $patch = min(100, max(0, (int) ($slices[2] ?? 0))); + return $major * 10000 + $minor * 100 + $patch; + } + } + public function errorResponseIfNotUserHasLevel($currentStatus, &$response, $user, $required_level_name, $message = 'You are not authorized to do this') { if ($user === false || $currentStatus) { diff --git a/src/constants.php b/src/constants.php index e0879d2..bb5db77 100644 --- a/src/constants.php +++ b/src/constants.php @@ -45,11 +45,25 @@ function double_map($array) 'cgit' => 4, ]), 'asset_edit_fields' => [ - 'title', 'description', 'category_id', + 'title', 'description', 'category_id', 'godot_version', 'version_string', 'cost', 'download_provider', 'download_commit', 'browse_url', 'issues_url', 'icon_url', ], 'asset_edit_preview_fields' => [ 'type', 'link', 'thumbnail', + ], + 'special_godot_versions' => double_map([ + 0 => 'unknown', + 9999999 => 'custom' + ]), + 'common_godot_versions' => [ + '1.0', + '1.1', + '2.0', //'2.0.1', '2.0.2', '2.0.3', '2.0.4', + '2.1', '2.1.1', '2.1.2', '2.1.3', '2.1.4', + '2.2', + '3.0', //'3.1' + 'unknown', + 'custom', ] ]; diff --git a/src/queries.php b/src/queries.php index 639eae4..b8fcdb4 100644 --- a/src/queries.php +++ b/src/queries.php @@ -19,15 +19,16 @@ LIMIT :page_size OFFSET :skip_count', ], 'category' => [ - 'list' => 'SELECT category_id as id, category as name FROM `as_categories` WHERE category_type LIKE :category_type ORDER BY category_id', + 'list' => 'SELECT category_id as id, category as name, category_type as type FROM `as_categories` WHERE category_type LIKE :category_type ORDER BY category_id', ], 'asset' => [ - 'search' => 'SELECT asset_id, title, username as author, user_id as author_id, category, category_id, rating, cost, support_level, icon_url, version, version_string FROM `as_assets` + 'search' => 'SELECT asset_id, title, username as author, user_id as author_id, category, category_id, godot_version, rating, cost, support_level, icon_url, version, version_string FROM `as_assets` LEFT JOIN `as_users` USING (user_id) LEFT JOIN `as_categories` USING (category_id) WHERE searchable = TRUE AND category_id LIKE :category AND category_type LIKE :category_type AND support_level RLIKE :support_levels_regex AND username LIKE :username + AND godot_version <= :max_godot_version AND godot_version >= :min_godot_version AND ( title LIKE :filter OR cost LIKE :filter @@ -61,13 +62,14 @@ LEFT JOIN `as_categories` USING (category_id) WHERE searchable = TRUE AND category_id LIKE :category AND category_type LIKE :category_type AND support_level RLIKE :support_levels_regex AND username LIKE :username + AND godot_version <= :max_godot_version AND godot_version >= :min_godot_version AND ( title LIKE :filter OR cost LIKE :filter OR username LIKE :filter )', - 'get_one' => 'SELECT asset_id, category_type, title, username as author, user_id as author_id, version, version_string, category, category_id, rating, cost, description, support_level, download_provider, download_commit, download_hash, browse_url, issues_url, icon_url, preview_id, `as_asset_previews`.type, link, thumbnail, searchable FROM `as_assets` + 'get_one' => 'SELECT asset_id, category_type, title, username as author, user_id as author_id, version, version_string, category, category_id, godot_version, rating, cost, description, support_level, download_provider, download_commit, download_hash, browse_url, issues_url, icon_url, preview_id, `as_asset_previews`.type, link, thumbnail, searchable FROM `as_assets` LEFT JOIN `as_categories` USING (category_id) LEFT JOIN `as_users` USING (user_id) LEFT JOIN `as_asset_previews` USING (asset_id) @@ -77,13 +79,13 @@ 'get_one_preview_bare' => 'SELECT * FROM `as_asset_previews` WHERE preview_id = :preview_id', 'apply_creational_edit' => 'INSERT INTO `as_assets` - SET title=:title, description=:description, category_id=:category_id, user_id=:user_id, + SET user_id=:user_id, title=:title, description=:description, category_id=:category_id, godot_version=:godot_version, version_string=:version_string, cost=:cost, download_provider=:download_provider, download_commit=:download_commit, download_hash=:download_hash, browse_url=:browse_url, issues_url=:issues_url, icon_url=:icon_url, version=0+:update_version, rating=0, searchable=TRUE', 'apply_edit' => 'UPDATE `as_assets` - SET title=COALESCE(:title, title), description=COALESCE(:description, description), category_id=COALESCE(:category_id, category_id), version_string=COALESCE(:version_string, version_string), cost=COALESCE(:cost, cost), + SET title=COALESCE(:title, title), description=COALESCE(:description, description), category_id=COALESCE(:category_id, category_id), godot_version=COALESCE(:godot_version, godot_version), version_string=COALESCE(:version_string, version_string), cost=COALESCE(:cost, cost), download_provider=COALESCE(:download_provider, download_provider), download_commit=COALESCE(:download_commit, download_commit), download_hash=COALESCE(:download_hash, download_hash), browse_url=COALESCE(:browse_url, browse_url), issues_url=COALESCE(:issues_url, issues_url), icon_url=COALESCE(:icon_url, icon_url), version=version+:update_version WHERE asset_id=:asset_id', @@ -101,7 +103,7 @@ WHERE asset_id=:asset_id' ], 'asset_edit' => [ - 'get_one' => 'SELECT edit_id, `as_asset_edits`.asset_id, user_id, title, description, category_id, version_string, + 'get_one' => 'SELECT edit_id, `as_asset_edits`.asset_id, user_id, title, description, category_id, godot_version, version_string, cost, download_provider, download_commit, browse_url, issues_url, icon_url, status, reason, edit_preview_id, `as_asset_previews`.preview_id, `as_asset_edit_previews`.type, `as_asset_edit_previews`.link, `as_asset_edit_previews`.thumbnail, `as_asset_edit_previews`.operation, `as_asset_previews`.type AS orig_type, `as_asset_previews`.link AS orig_link, `as_asset_previews`.thumbnail AS orig_thumbnail, @@ -118,7 +120,15 @@ 'get_editable_by_asset_id' => 'SELECT * FROM `as_asset_edits` WHERE asset_id=:asset_id AND status=0', 'search' => 'SELECT edit_id, asset_id, - `as_asset_edits`.user_id, COALESCE(`as_asset_edits`.title, `as_assets`.title) AS title, COALESCE(`as_asset_edits`.description, `as_assets`.description) AS description, category, COALESCE(`as_asset_edits`.version_string, `as_assets`.version_string) AS version_string, COALESCE(`as_asset_edits`.cost, `as_assets`.cost) AS cost, COALESCE(`as_asset_edits`.browse_url, `as_assets`.browse_url) AS browse_url, COALESCE(`as_asset_edits`.icon_url, `as_assets`.icon_url) AS icon_url, `as_assets`.support_level, status, reason, username AS author FROM `as_asset_edits` + `as_asset_edits`.user_id, + COALESCE(`as_asset_edits`.title, `as_assets`.title) AS title, + COALESCE(`as_asset_edits`.description, `as_assets`.description) AS description, + COALESCE(`as_asset_edits`.godot_version, `as_assets`.godot_version) AS godot_version, + COALESCE(`as_asset_edits`.version_string, `as_assets`.version_string) AS version_string, + COALESCE(`as_asset_edits`.cost, `as_assets`.cost) AS cost, + COALESCE(`as_asset_edits`.browse_url, `as_assets`.browse_url) AS browse_url, + COALESCE(`as_asset_edits`.icon_url, `as_assets`.icon_url) AS icon_url, + category, `as_assets`.support_level, status, reason, username AS author FROM `as_asset_edits` LEFT JOIN `as_users` USING (user_id) LEFT JOIN `as_categories` USING (category_id) LEFT JOIN `as_assets` USING (asset_id) @@ -145,12 +155,12 @@ ', 'submit' => 'INSERT INTO `as_asset_edits` - SET asset_id=:asset_id, user_id=:user_id, title=:title, description=:description, category_id=:category_id, version_string=:version_string, + SET asset_id=:asset_id, user_id=:user_id, title=:title, description=:description, category_id=:category_id, godot_version=:godot_version, version_string=:version_string, cost=:cost, download_provider=:download_provider, download_commit=:download_commit, browse_url=:browse_url, issues_url=:issues_url, icon_url=:icon_url, status=0, submit_date=NOW()', 'update' => 'UPDATE `as_asset_edits` - SET title=:title, description=:description, category_id=:category_id, version_string=:version_string, cost=:cost, + SET title=:title, description=:description, category_id=:category_id, godot_version=:godot_version, version_string=:version_string, cost=:cost, download_provider=:download_provider, download_commit=:download_commit, browse_url=:browse_url, issues_url=:issues_url, icon_url=:icon_url WHERE edit_id=:edit_id AND status=0', @@ -164,6 +174,7 @@ 'set_asset_id' => 'UPDATE `as_asset_edits` SET asset_id=:asset_id WHERE edit_id=:edit_id', 'set_status_and_reason' => 'UPDATE `as_asset_edits` SET status=:status, reason=:reason WHERE edit_id=:edit_id', - 'delete' => 'UPDATE `as_assets` SET searchable=0 WHERE asset_id=:asset_id' + 'delete' => 'UPDATE `as_assets` SET searchable=FALSE WHERE asset_id=:asset_id', + 'undelete' => 'UPDATE `as_assets` SET searchable=TRUE WHERE asset_id=:asset_id' ] ]; diff --git a/src/routes/asset.php b/src/routes/asset.php index ef82a07..bd83741 100644 --- a/src/routes/asset.php +++ b/src/routes/asset.php @@ -19,6 +19,8 @@ $page_size = 10; $max_page_size = 500; $page_offset = 0; + $min_godot_version = 0; + $max_godot_version = 9999999; if (isset($params['category']) && $params['category'] != "") { $category = (int) $params['category']; } @@ -50,6 +52,12 @@ if (isset($params['max_results'])) { $page_size = min(abs((int) $params['max_results']), $max_page_size); } + if (isset($params['godot_version']) && $params['godot_version'] != '') { + $godot_version = $this->utils->getUnformattedGodotVersion($params['godot_version']); + $min_godot_version = floor($godot_version / 10000) * 10000; // Keep just the major version + $max_godot_version = $godot_version; // Assume version requested can't handle future patches + // $max_godot_version = floor($godot_version / 100) * 100 + 99; // Assume future patches will work + } if (isset($params['page'])) { $page_offset = abs((int) $params['page']) * $page_size; } elseif (isset($params['offset'])) { @@ -79,6 +87,8 @@ $query = $this->queries['asset']['search']; $query->bindValue(':category', $category); $query->bindValue(':category_type', $category_type, PDO::PARAM_INT); + $query->bindValue(':min_godot_version', $min_godot_version, PDO::PARAM_INT); + $query->bindValue(':max_godot_version', $max_godot_version, PDO::PARAM_INT); $query->bindValue(':support_levels_regex', $support_levels); $query->bindValue(':filter', $filter); $query->bindValue(':username', $username); @@ -96,6 +106,8 @@ $query_count = $this->queries['asset']['search_count']; $query_count->bindValue(':category', $category, PDO::PARAM_INT); $query_count->bindValue(':category_type', $category_type, PDO::PARAM_INT); + $query_count->bindValue(':min_godot_version', $min_godot_version, PDO::PARAM_INT); + $query_count->bindValue(':max_godot_version', $max_godot_version, PDO::PARAM_INT); $query_count->bindValue(':support_levels_regex', $support_levels); $query_count->bindValue(':filter', $filter); $query_count->bindValue(':username', $username); @@ -112,7 +124,8 @@ $context = $this; $assets = array_map(function ($asset) use ($context) { - $asset["support_level"] = $context->constants['support_level'][(int) $asset['support_level']]; + $asset['godot_version'] = $this->utils->getFormattedGodotVersion((int) $asset['godot_version']); + $asset['support_level'] = $context->constants['support_level'][(int) $asset['support_level']]; return $asset; }, $assets); @@ -160,6 +173,8 @@ $asset_info["support_level"] = $this->constants['support_level'][(int) $value]; } elseif ($column==="download_provider") { $asset_info["download_provider"] = $this->constants['download_provider'][(int) $value]; + } elseif ($column==="godot_version") { + $asset_info["godot_version"] = $this->utils->getFormattedGodotVersion((int) $value); } else { $asset_info[$column] = $value; } @@ -261,4 +276,27 @@ ], 200); }); +/* + * Delete asset from library + */ +$app->post('/asset/{id:[0-9]+}/undelete', function ($request, $response, $args) { + + $body = $request->getParsedBody(); + + $error = $this->utils->ensureLoggedIn(false, $response, $body, $user); + $error = $this->utils->errorResponseIfNotOwner($error, $response, $user, $args['id']); + + if($error) return $response; + + $query = $this->queries['asset_edit']['undelete']; + $query->bindValue(':asset_id', (int) $args['id'], PDO::PARAM_INT); + $query->execute(); + + $error = $this->utils->errorResponseIfQueryBad(false, $response, $query); + if($error) return $response; + return $response->withJson([ + 'changed' => true, + 'url' => 'asset/', + ], 200); +}); diff --git a/src/routes/asset_edit.php b/src/routes/asset_edit.php index 0ea9b46..29d8e0e 100644 --- a/src/routes/asset_edit.php +++ b/src/routes/asset_edit.php @@ -87,6 +87,9 @@ function _insert_asset_edit_fields($c, $error, &$response, $query, $body, $requi unset($body['issues_url']); } } + if (isset($body['godot_version'])) { + $body['godot_version'] = $c->utils->getUnformattedGodotVersion($body['godot_version']); + } foreach ($c->constants['asset_edit_fields'] as $i => $field) { if (!$required) { @@ -320,6 +323,7 @@ function _add_previews_to_edit($c, $error, &$response, $edit_id, $previews, $ass $context = $this; $asset_edits = array_map(function ($asset_edit) use ($context) { $asset_edit['status'] = $context->constants['edit_status'][(int) $asset_edit['status']]; + $asset_edit['godot_version'] = $this->utils->getFormattedGodotVersion((int) $asset_edit['godot_version']); $asset_edit['support_level'] = $context->constants['support_level'][(int) $asset_edit['support_level']]; return $asset_edit; }, $asset_edits); @@ -377,6 +381,8 @@ function _add_previews_to_edit($c, $error, &$response, $edit_id, $previews, $ass $asset_edit['status'] = $this->constants['edit_status'][(int) $value]; } elseif ($column==='download_provider') { $asset_edit['download_provider'] = $this->constants['download_provider'][(int) $value]; + } elseif ($column==='godot_version') { + $asset_edit['godot_version'] = $this->utils->getFormattedGodotVersion((int) $value); } else { $asset_edit[$column] = $value; } @@ -412,6 +418,7 @@ function _add_previews_to_edit($c, $error, &$response, $edit_id, $previews, $ass $asset_edit['original'] = $asset; $asset_edit['original']['download_provider'] = $this->constants['download_provider'][$asset['download_provider']]; + $asset_edit['original']['godot_version'] = $this->utils->getFormattedGodotVersion($asset['godot_version']); if ($asset_edit['browse_url'] || $asset_edit['download_provider'] || $asset_edit['download_commit']) { $asset_edit['download_url'] = $this->utils->getComputedDownloadUrl( diff --git a/style/base.css b/style/base.css new file mode 100644 index 0000000..754a020 --- /dev/null +++ b/style/base.css @@ -0,0 +1,24 @@ +.form-search .form-group { + margin-bottom: 0.2em; + margin-right: 40px; +} +@media screen and (max-width: 768px) { + .form-search .form-group { + margin-right: 0; + } +} +@supports (display: flex) { + @media screen and (min-width: 768px) { + .form-search { + display: flex; + justify-content: space-between; + flex-flow: wrap; + } + .form-search .form-group { + margin-right: 1em; + margin-left: 1em; + flex-shrink: 0; + display: block; + } + } +} diff --git a/templates/_asset_fields.phtml b/templates/_asset_fields.phtml index c82e3c6..65f0b97 100644 --- a/templates/_asset_fields.phtml +++ b/templates/_asset_fields.phtml @@ -36,6 +36,24 @@ $_asset_values = array_merge([ +
+ +
+ + The version of Godot the asset works with +
+
+
diff --git a/templates/_header.phtml b/templates/_header.phtml index 451fba7..a9400dc 100644 --- a/templates/_header.phtml +++ b/templates/_header.phtml @@ -21,6 +21,7 @@ + diff --git a/templates/asset.phtml b/templates/asset.phtml index c55afe9..599fe61 100644 --- a/templates/asset.phtml +++ b/templates/asset.phtml @@ -11,6 +11,7 @@ + "> +
+
+ + +