diff --git a/.gitignore b/.gitignore index 62caf91..20e96dc 100644 --- a/.gitignore +++ b/.gitignore @@ -23,4 +23,6 @@ dist-ssr *.sln *.sw? -public/vendor +# php +/public/vendor +/api/vendor diff --git a/composer.json b/composer.json index 25dbb2a..ae334d7 100644 --- a/composer.json +++ b/composer.json @@ -3,7 +3,8 @@ "vendor-dir": "public/vendor" }, "require": { + "bramus/router": "1.5", "vlucas/phpdotenv": "^5.4", - "firebase/php-jwt": "^6.2" + "catfan/medoo": "^2.1" } } diff --git a/composer.lock b/composer.lock index 222872d..1716197 100644 --- a/composer.lock +++ b/composer.lock @@ -4,69 +4,134 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "5e6e41d564a162322502fd4108ce44cf", + "content-hash": "a72d198969a21ad6ddd90355a3227085", "packages": [ { - "name": "firebase/php-jwt", - "version": "v6.2.0", + "name": "bramus/router", + "version": "1.5", "source": { "type": "git", - "url": "https://github.com/firebase/php-jwt.git", - "reference": "d28e6df83830252650da4623c78aaaf98fb385f3" + "url": "https://github.com/bramus/router.git", + "reference": "6adc0182dc6b0ebc22fd10543f65a36de10d8c05" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/firebase/php-jwt/zipball/d28e6df83830252650da4623c78aaaf98fb385f3", - "reference": "d28e6df83830252650da4623c78aaaf98fb385f3", + "url": "https://api.github.com/repos/bramus/router/zipball/6adc0182dc6b0ebc22fd10543f65a36de10d8c05", + "reference": "6adc0182dc6b0ebc22fd10543f65a36de10d8c05", "shasum": "" }, "require": { - "php": "^7.1||^8.0" + "php": ">=5.3.0" }, "require-dev": { - "guzzlehttp/guzzle": "^6.5||^7.4", - "phpspec/prophecy-phpunit": "^1.1", - "phpunit/phpunit": "^7.5||^9.5", - "psr/cache": "^1.0||^2.0", - "psr/http-client": "^1.0", - "psr/http-factory": "^1.0" - }, - "suggest": { - "paragonie/sodium_compat": "Support EdDSA (Ed25519) signatures when libsodium is not present" + "friendsofphp/php-cs-fixer": "~2.14", + "phpunit/php-code-coverage": "~2.0", + "phpunit/phpunit": "~4.0" }, "type": "library", "autoload": { - "psr-4": { - "Firebase\\JWT\\": "src" + "psr-0": { + "Bramus": "src/" } }, "notification-url": "https://packagist.org/downloads/", "license": [ - "BSD-3-Clause" + "MIT" ], "authors": [ { - "name": "Neuman Vong", - "email": "neuman+pear@twilio.com", - "role": "Developer" - }, - { - "name": "Anant Narayanan", - "email": "anant@php.net", - "role": "Developer" + "name": "Bram(us) Van Damme", + "email": "bramus@bram.us", + "homepage": "http://www.bram.us" } ], - "description": "A simple library to encode and decode JSON Web Tokens (JWT) in PHP. Should conform to the current spec.", - "homepage": "https://github.com/firebase/php-jwt", + "description": "A lightweight and simple object oriented PHP Router", + "homepage": "https://github.com/bramus/router", "keywords": [ - "jwt", - "php" + "router", + "routing" ], "support": { - "issues": "https://github.com/firebase/php-jwt/issues", - "source": "https://github.com/firebase/php-jwt/tree/v6.2.0" + "issues": "https://github.com/bramus/router/issues", + "source": "https://github.com/bramus/router/tree/1.5" }, - "time": "2022-05-13T20:54:50+00:00" + "time": "2020-10-26T09:50:48+00:00" + }, + { + "name": "catfan/medoo", + "version": "v2.1.7", + "source": { + "type": "git", + "url": "https://github.com/catfan/Medoo.git", + "reference": "74be58f80d330d1075ef3bfd0fb3d057349597ae" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/catfan/Medoo/zipball/74be58f80d330d1075ef3bfd0fb3d057349597ae", + "reference": "74be58f80d330d1075ef3bfd0fb3d057349597ae", + "shasum": "" + }, + "require": { + "ext-pdo": "*", + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.0" + }, + "suggest": { + "ext-pdo_dblib": "For MSSQL or Sybase database on Linux/UNIX platform", + "ext-pdo_mysql": "For MySQL or MariaDB database", + "ext-pdo_oci": "For Oracle database", + "ext-pdo_pqsql": "For PostgreSQL database", + "ext-pdo_sqlite": "For SQLite database", + "ext-pdo_sqlsrv": "For MSSQL database on both Window/Liunx platform" + }, + "type": "framework", + "autoload": { + "psr-4": { + "Medoo\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Angel Lai", + "email": "angel@medoo.in" + } + ], + "description": "The lightweight PHP database framework to accelerate development", + "homepage": "https://medoo.in", + "keywords": [ + "database", + "database library", + "lightweight", + "mariadb", + "mssql", + "mysql", + "oracle", + "php framework", + "postgresql", + "sql", + "sqlite" + ], + "support": { + "issues": "https://github.com/catfan/Medoo/issues", + "source": "https://github.com/catfan/Medoo" + }, + "funding": [ + { + "url": "https://paypal.me/AngelaonLai", + "type": "custom" + }, + { + "url": "https://opencollective.com/medoo", + "type": "open_collective" + } + ], + "time": "2022-07-02T04:27:50+00:00" }, { "name": "graham-campbell/result-type", diff --git a/index.html b/index.html index 13496b3..08cd2ac 100644 --- a/index.html +++ b/index.html @@ -5,7 +5,15 @@ - Title + Erant + + + diff --git a/package-lock.json b/package-lock.json index 3268bb7..6c2fd13 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,7 +8,8 @@ "name": "geohry", "version": "0.0.0", "dependencies": { - "svelte-routing": "^1.6.0" + "svelte-routing": "^1.6.0", + "yallist": "^4.0.0" }, "devDependencies": { "@sveltejs/vite-plugin-svelte": "^1.0.1", @@ -1888,14 +1889,10 @@ "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", "dev": true }, - "node_modules/xtend": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", - "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", - "dev": true, - "engines": { - "node": ">=0.4" - } + "node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" }, "node_modules/yaml": { "version": "2.1.1", @@ -3065,17 +3062,24 @@ "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", "dev": true }, +<<<<<<< HEAD "xtend": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", "dev": true - }, - "yaml": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.1.1.tgz", - "integrity": "sha512-o96x3OPo8GjWeSLF+wOAbrPfhFOGY0W00GNaxCDv+9hkcDJEnev1yh8S7pgHF0ik6zc8sQLuL8hjHjJULZp8bw==", - "dev": true +======= + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" +>>>>>>> master + }, + "yaml": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.1.1.tgz", + "integrity": "sha512-o96x3OPo8GjWeSLF+wOAbrPfhFOGY0W00GNaxCDv+9hkcDJEnev1yh8S7pgHF0ik6zc8sQLuL8hjHjJULZp8bw==", + "dev": true + } } } -} diff --git a/package.json b/package.json index 668cde5..fc0dcf0 100644 --- a/package.json +++ b/package.json @@ -6,7 +6,8 @@ "scripts": { "dev": "vite", "build": "vite build", - "preview": "vite preview" + "preview": "vite preview", + "php": "php -S localhost:8000 -t ./public" }, "devDependencies": { "@sveltejs/vite-plugin-svelte": "^1.0.1", @@ -20,6 +21,7 @@ "vite": "^3.0.0" }, "dependencies": { - "svelte-routing": "^1.6.0" + "svelte-routing": "^1.6.0", + "yallist": "^4.0.0" } } diff --git a/public/.env b/public/.env deleted file mode 100644 index 42a89c3..0000000 --- a/public/.env +++ /dev/null @@ -1,39 +0,0 @@ -#database configuration - -#database host -DB_HOST="localhost" -#database user -DB_USER="root" -#database user password -DB_PASS="" -#database name -DB_NAME="test" -#database port -DB_PORT="mysql" - -#should connect to database? (false if you don't want to use database) -DB_ENABLED=false - -#production flag (true if you want to use production settings) -PRODUCTION=false -#error reporting (true if you want to report errors) -ERROR_REPORTING=true - -#character set for whole application -CHARSET="utf-8" - -#should force redirect to https? (true if you want to use https) -FORCE_HTTPS=false - -#jwt token authentication - -#jwt key for token authentication -#online secure passwords generator - https://www.grc.com/passwords.htm -#generate key by PHP - $jwtKey = bin2hex(random_bytes(32)); -JWT_KEY="" -#encryption algorithm for jwt token -JWT_ALGO="HS256" -#jwt token server name -SERVER_NAME="http://localhost" -#jwt token expiration time in seconds -JWT_EXPIRATION_TIME=3600 diff --git a/public/.htaccess b/public/.htaccess index daad08f..833f494 100644 --- a/public/.htaccess +++ b/public/.htaccess @@ -1,15 +1,10 @@ - + Order Allow,Deny Deny from all - - RewriteEngine On +RewriteEngine On - # RewriteCond %{HTTPS} off - # RewriteRule .* https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301] - - RewriteCond %{REQUEST_FILENAME} !-f - RewriteCond %{REQUEST_FILENAME} !-d - RewriteRule . index.php [L] - +RewriteCond %{REQUEST_FILENAME} !-f +RewriteCond %{REQUEST_FILENAME} !-d +RewriteRule . index.php [L] diff --git a/public/api/.env b/public/api/.env new file mode 100644 index 0000000..72ef434 --- /dev/null +++ b/public/api/.env @@ -0,0 +1,6 @@ +PRODUCTION=false + +DB_HOST="db.db030.webglobe.com" +DB_USER="mysql85033" +DB_PASSWORD="troglodyt" +DB_DATABASE="mysql122279" diff --git a/public/api/index.php b/public/api/index.php new file mode 100644 index 0000000..3fc8db0 --- /dev/null +++ b/public/api/index.php @@ -0,0 +1,64 @@ +load(); + +function env($key) { + global $_ENV; + return array_key_exists($key, $_ENV) ? $_ENV[$key] : null; +} + +$database = new Medoo([ + 'type' => 'mysql', + 'host' => env("DB_HOST"), + 'database' => env("DB_DATABASE"), + 'username' => env("DB_USER"), + 'password' => env("DB_PASSWORD") +]); + +$data = json_decode(file_get_contents("php://input"), true); +$routesDirectory = __DIR__ . "/routes"; + +$getFolderContentUtil = null; +$getFolderContentUtil = function($dir) use($routesDirectory, &$getFolderContentUtil, $router, $data, $database) { + $files = scandir($dir); + $filter = '/\.php$/'; + + foreach($files as $key => $value) { + $path = realpath($dir.DIRECTORY_SEPARATOR.$value); + $pathWithoutRoot = str_replace($routesDirectory, '', $path); + $pathWithoutRelativeRoot = str_replace($dir, '', $path); + + if(!is_dir($path)) { + if(empty($filter) || preg_match($filter, $path)) { + $error = false; + $response = require $path; + + if(!empty($response) && is_array($response)) { + foreach($response as $key => $fn) { + $router->{$key}(str_replace(".php", '', $pathWithoutRelativeRoot), function() use($router, $fn, $data, $error, $database) { + $responseResult = $fn($data, getallheaders(), $database, $error, $router); + if($responseResult) { + $responseResult["status"] = array_key_exists("status", $responseResult) ? $responseResult["status"] : 200; + http_response_code($responseResult["status"]); + echo json_encode($responseResult["data"]); + exit(); + } + }); + } + } + } + } else if($value != "." && $value != "..") { + $router->mount($pathWithoutRelativeRoot, function() use($getFolderContentUtil, $path, $filter) { + $getFolderContentUtil($path); + }); + } + } +}; + +$getFolderContentUtil($routesDirectory); + +$router->run(); diff --git a/public/api/routes/game/details.php b/public/api/routes/game/details.php new file mode 100644 index 0000000..3d2b55e --- /dev/null +++ b/public/api/routes/game/details.php @@ -0,0 +1,74 @@ + function($data, $headers, $db) { + function remoteFileExists($url) { + $curl = curl_init($url); + + //don't fetch the actual page, you only want to check the connection is ok + curl_setopt($curl, CURLOPT_NOBODY, true); + + //do request + $result = curl_exec($curl); + + $ret = false; + + //if request did not fail + if ($result !== false) { + //if request was ok, check response code + $statusCode = curl_getinfo($curl, CURLINFO_HTTP_CODE); + + if ($statusCode == 200) { + $ret = true; + } + } + + curl_close($curl); + + return $ret; + } + + $imagesHostName = 'https://geohry.skolazdola.cz/'; + + if(!isset($data['gameurl']) || empty($data['gameurl'])) return [ + "data" => [ + "success" => false, + "message" => "Property 'gameurl' is not set." + ] + ]; + + $gameUrl = $data['gameurl']; + + $gameDetails = $db->select('games4', '*', [ + 'url' => $gameUrl + ]); + + if(!$gameDetails) return [ + "data" => [ + "success" => false, + "message" => "Invalid 'gameurl'." + ] + ]; + + $gameDetails = $gameDetails[0]; + + $gameDetails["questions"] = $db->select('questions4', '*', [ + 'url' => $gameUrl + ]); + + $thumbnailPath = "{$imagesHostName}/games/{$gameUrl}/intro.jpg"; + $gameDetails["thumbnail"] = remoteFileExists($thumbnailPath) ? $thumbnailPath : null; + + foreach($gameDetails["questions"] as &$question) { + $questionThumbnailPath = "{$imagesHostName}/games/{$gameUrl}/" . $question["uniqid"] . ".jpg"; + $question["thumbnail"] = remoteFileExists($questionThumbnailPath) ? $questionThumbnailPath : null; + } + + return [ + "success" => true, + "data" => $gameDetails + ]; + } + +]; diff --git a/public/cors.php b/public/cors.php new file mode 100644 index 0000000..cb7bd5f --- /dev/null +++ b/public/cors.php @@ -0,0 +1,37 @@ +load(); +cors(); -function env($key, $default = null) { - global $envFile; +$router = new \Bramus\Router\Router(); +$router->setBasePath('/'); - if(isset($envFile[$key])) { - return $envFile[$key]; - } +$router->mount("/api", function() use($router) { + require_once __DIR__ . '/api/index.php'; +}); - return $default; -} +$router->set404('/api(/.*)?', function() { + header('HTTP/1.1 404 Not Found'); + header('Content-Type: application/json'); -header('Content-Type: text/html; charset=' . env("CHARSET")); -require_once(__DIR__ . '/index.html'); + echo json_encode([ + "message" => "Route not defined." + ]); +}); + +$router->get("/.*", function() { + header('Content-Type: text/html; charset=UTF-8'); + echo "frontend!"; +}); + + +$router->run(); diff --git a/src/lib/utils/api.js b/src/lib/utils/api.js new file mode 100644 index 0000000..9f5f8d3 --- /dev/null +++ b/src/lib/utils/api.js @@ -0,0 +1,60 @@ +async function send({ method, path, body, token, headers }) { + const opts = { method, headers: new Headers(), mode: 'cors' } + opts.headers.append('Content-Type', 'application/json') + opts.headers.append('Access-Control-Allow-Origin', '*') + + if (body) { + opts.body = JSON.stringify(body) + } + + if (headers) { + for (const [k, v] of Object.entries(headers)) { + opts.headers.append(k, v) + } + } + + if (token) { + opts.headers['Authorization'] = `Bearer ${token}` + } + + const res = fetch(path, opts) + .then(async (r) => { + if (r.status >= 200 && r.status < 400) { + return await r.text() + } else { + return await r.text() + } + }) + .then((str) => { + try { + return JSON.parse(str) + } catch (err) { + return str + } + }) + + return res +} + +export function get(path, token = null) { + return send({ method: 'GET', path, body: null, token }) +} + +export function del(path, token = null) { + return send({ method: 'DELETE', path, body: null, token }) +} + +export function post(path, body, token = null) { + return send({ method: 'POST', path, body, token }) +} + +export function put( + path, + body, + token = null, + headers = [] +) { + return send({ method: 'PUT', path, body, token, headers }) +} + +export const hostName = 'https://erant.cz/api' \ No newline at end of file diff --git a/src/lib/utils/parseQuestion.js b/src/lib/utils/parseQuestion.js new file mode 100644 index 0000000..126ff44 --- /dev/null +++ b/src/lib/utils/parseQuestion.js @@ -0,0 +1,16 @@ + +export default (question, questionType) => { + switch (questionType.toLowerCase()) { + case 'text': + return question + case 'number': + return Number.parseFloat(question) + case 'choice': + return question.split(/;\s*/).map(item => ({ + label: item.startsWith('*') ? item.substring(1) : item, + value: item.startsWith('*') ? true : false + })) + default: + return null + } +} diff --git a/src/routes/game.svelte b/src/routes/game.svelte index 6d6493e..ee41992 100644 --- a/src/routes/game.svelte +++ b/src/routes/game.svelte @@ -9,8 +9,24 @@ import Map from '../lib/Components/game/Map.svelte' import ImageSlider from '../lib/Components/ImageSlider.svelte' + import * as api from '$lib/utils/api' + import parseQuestion from '$lib/utils/parseQuestion' + import yallist from 'yallist' + let background = '/assets/temp/kar1.png' let assets = Array.from(Array(6).keys()).map((_, i) => `/assets/temp/kar${i + 1}.png`) + + ;(async () => { + const gameData = await api.post(`${api.hostName}/game/details`, { + gameurl: 'pisek-mesto-kralovske', + }) + + const questions = yallist(gameData.questions) + + console.log(questions) + + console.log(parseQuestion(gameData.questions[0].answer, gameData.questions[0].type)) + })() let shareData = { title: 'Geohry', text: 'Naše geohry',