Merge branch 'graphql' into 'master'

Rewrite API endpoint to graphql

See merge request jonasled/website!8
This commit is contained in:
Jonas Leder 2022-03-14 15:48:50 +01:00
commit b183bf90c1
29 changed files with 808 additions and 451 deletions

View file

@ -7,7 +7,7 @@ COPY . .
RUN mkdir public/js
RUN mkdir public/css
RUN yarn install --network-timeout 1000000
RUN yarn compile
RUN yarn build
# |--------------------------------------------------------------------------
# | Install PHP dependencies

View file

@ -1,7 +1,8 @@
{
"require": {
"aws/aws-sdk-php": "^3.181",
"guzzlehttp/guzzle": "^7.0"
"guzzlehttp/guzzle": "^7.0",
"webonyx/graphql-php": "^14.11"
},
"config": {
"vendor-dir": "public/API/vendor"

70
composer.lock generated
View file

@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "f47a9b8d286ca72493a7fe02f263976e",
"content-hash": "31a3a0321659f9c8afff63a68a9fafb6",
"packages": [
{
"name": "aws/aws-crt-php",
@ -669,6 +669,72 @@
}
],
"time": "2021-05-27T12:26:48+00:00"
},
{
"name": "webonyx/graphql-php",
"version": "v14.11.5",
"source": {
"type": "git",
"url": "https://github.com/webonyx/graphql-php.git",
"reference": "ffa431c0821821839370a68dab3c2597c06bf7f0"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/webonyx/graphql-php/zipball/ffa431c0821821839370a68dab3c2597c06bf7f0",
"reference": "ffa431c0821821839370a68dab3c2597c06bf7f0",
"shasum": ""
},
"require": {
"ext-json": "*",
"ext-mbstring": "*",
"php": "^7.1 || ^8"
},
"require-dev": {
"amphp/amp": "^2.3",
"doctrine/coding-standard": "^6.0",
"nyholm/psr7": "^1.2",
"phpbench/phpbench": "^1.2",
"phpstan/extension-installer": "^1.0",
"phpstan/phpstan": "0.12.82",
"phpstan/phpstan-phpunit": "0.12.18",
"phpstan/phpstan-strict-rules": "0.12.9",
"phpunit/phpunit": "^7.2 || ^8.5",
"psr/http-message": "^1.0",
"react/promise": "2.*",
"simpod/php-coveralls-mirror": "^3.0",
"squizlabs/php_codesniffer": "3.5.4"
},
"suggest": {
"psr/http-message": "To use standard GraphQL server",
"react/promise": "To leverage async resolving on React PHP platform"
},
"type": "library",
"autoload": {
"psr-4": {
"GraphQL\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"description": "A PHP port of GraphQL reference implementation",
"homepage": "https://github.com/webonyx/graphql-php",
"keywords": [
"api",
"graphql"
],
"support": {
"issues": "https://github.com/webonyx/graphql-php/issues",
"source": "https://github.com/webonyx/graphql-php/tree/v14.11.5"
},
"funding": [
{
"url": "https://opencollective.com/webonyx-graphql-php",
"type": "open_collective"
}
],
"time": "2022-01-24T11:13:31+00:00"
}
],
"packages-dev": [],
@ -679,5 +745,5 @@
"prefer-lowest": false,
"platform": [],
"platform-dev": [],
"plugin-api-version": "2.1.0"
"plugin-api-version": "2.0.0"
}

View file

@ -1,31 +1,31 @@
class blogFooter extends HTMLElement {
constructor(){
super();
let xhr = new XMLHttpRequest();
let ul = document.createElement("ul");
xhr.onreadystatechange = () => {
if(xhr.readyState === 4) {
if (xhr.status === 200) {
let blog = JSON.parse(xhr.responseText);
blog.forEach((element) => {
let li = document.createElement("li");
let a = document.createElement("a");
a.href = "/post.html?id=" + element["id"];
a.innerText = element["title"];
li.appendChild(a);
ul.appendChild(li);
});
this.appendChild(ul);
} else {
let p = document.createElement("p");
p.innerText = "Leider konnte dieser Inhalt nicht geladen werden, bitte versuche die Seite neu zu laden oder komme später wieder zurück";
this.appendChild(p);
this.getBlogEntries();
}
}
}
async getBlogEntries() {
let ul = document.createElement("ul");
this.appendChild(ul);
var graphql = JSON.stringify({
query: 'query($count: Int!) { blogPosts(count: $count) { title id }}',
variables: {
"count": 5
}
xhr.open("GET", "/API/getBlogElements.php?position=footer");
xhr.send();
})
var requestOptions = {
method: 'POST',
body: graphql,
};
let posts = (await (await fetch("http://localhost:1234/API/graphql.php", requestOptions)).json()).data.blogPosts;
posts.forEach((element) => {
let li = document.createElement("li");
let a = document.createElement("a");
a.href = "/post.html?id=" + element["id"];
a.innerText = element["title"];
li.appendChild(a);
ul.appendChild(li);
});
}
}

View file

@ -1,48 +1,48 @@
class BlogIndex extends HTMLElement {
constructor() {
super();
let xhr = new XMLHttpRequest();
xhr.onreadystatechange = () => {
if (xhr.readyState === 4) {
if (xhr.status === 200) {
let blog = JSON.parse(xhr.responseText);
blog.forEach((element) => {
const article = document.createElement("article");
article.classList.add("breakWord");
this.appendChild(article);
this.getBlogPosts();
}
const h2 = document.createElement("h2");
h2.innerText = element["title"];
article.appendChild(h2);
const content = document.createElement("p");
content.classList.add("breakWord");
content.innerHTML = element["content"];
article.appendChild(content);
const moreP = document.createElement("p");
moreP.classList.add("center");
article.appendChild(moreP);
const moreLink = document.createElement("a");
moreLink.href = "/post.html?id=" + element["id"];
moreP.appendChild(moreLink);
const moreButton = document.createElement("button");
moreButton.innerText = "Mehr lesen";
moreLink.appendChild(moreButton);
});
} else {
let p = document.createElement("p");
p.innerText = "Leider konnte dieser Inhalt nicht geladen werden, bitte versuche die Seite neu zu laden oder komme später wieder zurück";
this.appendChild(p);
}
}
async getBlogPosts() {
var graphql = JSON.stringify({
query: 'query($count: Int! $contentLength: Int!) { blogPosts(count: $count contentLength: $contentLength) { content title id }}',
variables: {
"count": 3,
"contentLength": 300
}
xhr.open("GET", "/API/getBlogElements.php?position=index");
xhr.send();
})
var requestOptions = {
method: 'POST',
body: graphql,
};
let posts = (await (await fetch("http://localhost:1234/API/graphql.php", requestOptions)).json()).data.blogPosts;
posts.forEach((element) => {
const article = document.createElement("article");
article.classList.add("breakWord");
this.appendChild(article);
const h2 = document.createElement("h2");
h2.innerText = element["title"];
article.appendChild(h2);
const content = document.createElement("p");
content.classList.add("breakWord");
content.innerHTML = element["content"];
article.appendChild(content);
const moreP = document.createElement("p");
moreP.classList.add("center");
article.appendChild(moreP);
const moreLink = document.createElement("a");
moreLink.href = "/post.html?id=" + element["id"];
moreP.appendChild(moreLink);
const moreButton = document.createElement("button");
moreButton.innerText = "Mehr lesen";
moreLink.appendChild(moreButton);
});
}
}

View file

@ -1,48 +1,46 @@
class commentsDisplay extends HTMLElement {
constructor() {
super();
let path = window.location.pathname;
let pageName = path.split("/").pop();
this.getComments()
}
let xhr = new XMLHttpRequest();
xhr.onreadystatechange = () => {
if (xhr.readyState === 4) {
if (xhr.status === 200) {
let comments = JSON.parse(xhr.responseText);
comments.forEach((element) => {
const h3 = document.createElement("h3");
h3.classList.add("commentTitle");
h3.innerText = element["name"];
this.appendChild(h3);
const commentDiv = document.createElement("div");
commentDiv.classList.add("comment");
this.appendChild(commentDiv);
const image = document.createElement("img");
image.src = element["gravatarURL"];
commentDiv.appendChild(image);
const article = document.createElement("article");
article.classList.add("commentArticle");
commentDiv.appendChild(article);
const commentText = document.createElement("p");
commentText.classList.add("commentText");
commentText.innerText = element["comment"];
article.appendChild(commentText);
});
} else {
let p = document.createElement("p");
p.innerText = "Leider konnte dieser Inhalt nicht geladen werden, bitte versuche die Seite neu zu laden oder komme später wieder zurück.";
this.appendChild(p);
}
}
async getComments() {
var graphql = JSON.stringify({
query: 'query($article: String!) { comments(article: $article) { name comment gravatarURL }}',
variables: {
"article": window.location.pathname
}
xhr.open("GET", "/API/projectComments.php?article=" + pageName);
xhr.send();
})
var requestOptions = {
method: 'POST',
body: graphql,
};
let comments = (await (await fetch("http://localhost:1234/API/graphql.php", requestOptions)).json()).data.comments;
this.innerHTML = "";
comments.forEach((element) => {
const h3 = document.createElement("h3");
h3.classList.add("commentTitle");
h3.innerText = element["name"];
this.appendChild(h3);
const commentDiv = document.createElement("div");
commentDiv.classList.add("comment");
this.appendChild(commentDiv);
const image = document.createElement("img");
image.src = element["gravatarURL"];
commentDiv.appendChild(image);
const article = document.createElement("article");
article.classList.add("commentArticle");
commentDiv.appendChild(article);
const commentText = document.createElement("p");
commentText.classList.add("commentText");
commentText.innerText = element["comment"];
article.appendChild(commentText);
});
}
}

View file

@ -6,7 +6,15 @@ class contactMailButton extends HTMLElement {
}
async addButton() {
let sitekey = await (await fetch("/API/config.php?name=sitekey")).text();
var graphql = JSON.stringify({
query: "query {sitekey}"
})
var requestOptions = {
method: 'POST',
body: graphql,
};
let sitekey = (await (await fetch("/API/graphql.php", requestOptions)).json()).data.sitekey;
console.log(sitekey);
this.innerHTML = `E-Mail: <button id="emailButton" class="h-captcha" data-sitekey="${sitekey}" data-callback="onSubmit">laden</button><br>`;
const script = document.createElement("script");

View file

@ -1,20 +1,24 @@
class ebkBanner extends HTMLElement {
constructor(){
super();
let xhr = new XMLHttpRequest();
xhr.onreadystatechange = () => {
if(xhr.readyState === 4 && xhr.status === 200){
if(xhr.responseText > 0) {
const h2 = document.createElement("h2");
h2.classList.add("red");
h2.innerHTML = "Ich biete aktuell wieder verschiedene Artikel zum verkauf an, eine genaue Übersicht ist <a class=\"red\" href=\"/selling.html\">hier</a> zu sehen."
this.appendChild(h2);
}
}
}
this.generateBanner();
}
xhr.open("GET", "/API/ebk.php?count");
xhr.send();
async generateBanner() {
var graphql = JSON.stringify({
query: 'query { ebayKleinanzeigen{ count }}',
})
var requestOptions = {
method: 'POST',
body: graphql,
};
let elementCount = (await (await fetch("http://localhost:1234/API/graphql.php", requestOptions)).json()).data.ebayKleinanzeigen.count;
if(elementCount > 0) {
const h2 = document.createElement("h2");
h2.classList.add("red");
h2.innerHTML = "Ich biete aktuell wieder verschiedene Artikel zum verkauf an, eine genaue Übersicht ist <a class=\"red\" href=\"/selling.html\">hier</a> zu sehen."
this.appendChild(h2);
}
}
}

View file

@ -8,31 +8,127 @@ class newComment extends HTMLElement {
}
async setupForm() {
let sitekey = await (await fetch("/API/config.php?name=sitekey")).text();
var graphql = JSON.stringify({
query: "query {sitekey}"
})
var requestOptions = {
method: 'POST',
body: graphql,
};
let sitekey = (await (await fetch("/API/graphql.php", requestOptions)).json()).data.sitekey;
let script = document.createElement('script');
script.src = "https://hCaptcha.com/1/api.js";
script.type = 'text/javascript';
script.onload = () => {
let pageName = window.location.pathname.split("/").pop();
this.parentElement.innerHTML = `
<form action="/API/newComment.php" method="post">
<label for="name">Name:</label><br>
<input type="text" id="name" name="name"><br><br>
let pageName = window.location.pathname
const parent = this.parentElement;
parent.innerHTML = "";
const form = document.createElement("form");
parent.appendChild(form);
const labelName = document.createElement("label")
labelName.setAttribute("for", "name");
labelName.innerText = "Name:";
form.appendChild(labelName);
const nameInput = document.createElement("input");
nameInput.type = "text";
nameInput.name = "name";
nameInput.id = "name";
form.appendChild(nameInput);
let linebreak = document.createElement("br");
form.appendChild(linebreak);
const labelMail = document.createElement("label")
labelMail.setAttribute("for", "email");
labelMail.innerText = "E-Mail: (wird nicht veröffentlicht)";
form.appendChild(labelMail);
const mailInput = document.createElement("input");
mailInput.type = "email";
mailInput.name = "email";
mailInput.id = "email";
form.appendChild(mailInput);
linebreak = document.createElement("br");
form.appendChild(linebreak);
const labelComment = document.createElement("label")
labelComment.setAttribute("for", "comment");
labelComment.innerText = "Kommentar:";
form.appendChild(labelComment);
const commentInput = document.createElement("textarea");
commentInput.name = "comment";
commentInput.id = "comment";
form.appendChild(commentInput);
<label for="email">E-Mail: (wird nicht ver&ouml;ffentlicht)</label><br>
<input type="text" id="email" name="email"><br><br>
linebreak = document.createElement("br");
form.appendChild(linebreak);
const hcaptcha = document.createElement("div");
hcaptcha.classList.add("h-captcha");
hcaptcha.setAttribute("data-theme", "dark");
hcaptcha.setAttribute("data-sitekey", sitekey);
form.appendChild(hcaptcha);
<label for="comment">Kommentar:</label><br>
<textarea name="comment" id="comment"></textarea><br><br>
<div class="h-captcha" data-theme="dark" data-sitekey="${sitekey}"></div><br>
<input type="hidden" name="pagename" id="pagename" value="${pageName}">
<input type="submit" value="Kommentar ver&ouml;ffentlichen"><br>
<p>Mit dem Klick auf den obigen Button erkl&auml;ren sie sich mit der <a href="/datenschutzerklaerung.html">Datenschutzerkl&auml;rung</a> einverstanden.</p>
</form>
`;
linebreak = document.createElement("br");
form.appendChild(linebreak);
const submitButton = document.createElement("input");
submitButton.value = "Kommentar veröffentlichen";
submitButton.type = "submit";
form.appendChild(submitButton);
const labelDatenschutz = document.createElement("p");
labelDatenschutz.innerText = "Mit dem Klick auf den obigen Button erklären sie sich mit der ";
form.appendChild(labelDatenschutz);
const datenschutzLink = document.createElement("a");
datenschutzLink.innerText = "Datenschutzerklärung";
datenschutzLink.href = "/datenschutzerklaerung.html";
labelDatenschutz.appendChild(datenschutzLink);
const datenschutzTextNode = document.createTextNode(" einverstanden");
labelDatenschutz.appendChild(datenschutzTextNode);
submitButton.onclick = async () => {
if(nameInput.value == "" || commentInput.value == "") {
alert("Name oder Kommentar nicht ausgefüllt.");
return;
}
var graphql = JSON.stringify({
query: 'query($article: String!, $name: String!, $hCaptchaResponse: String!, $email: String!, $comment: String!) { newComment(article: $article, name: $name, email: $email, comment: $comment, hCaptchaResponse: $hCaptchaResponse)}',
variables: {
"article": pageName,
"name": nameInput.value,
"email": mailInput.value,
"comment": commentInput.value,
"hCaptchaResponse": form.querySelector(".h-captcha iframe").getAttribute("data-hcaptcha-response")
}
})
var requestOptions = {
method: 'POST',
body: graphql,
};
let data = (await (await fetch("http://localhost:1234/API/graphql.php", requestOptions)).json()).data;
if(data.newComment == "OK"){
document.querySelector("jl-comments_display").getComments();
parent.innerHTML = "<jl-new_comment></jl-new_comment>"
} else {
alert("Fehler: " + data.newComment);
}
}
form.onsubmit = () => {
return false;
}
}
document.body.append(script);
}

View file

@ -1,13 +1,17 @@
import * as basicLightbox from 'basiclightbox'
class sellingTable extends HTMLElement {
constructor(){
const config = [
constructor() {
super();
this.config = [
{
"title": "Bild",
"fieldName": "previewImage",
"fieldName": "preview",
"displayType": "image",
"fullImage": "image"
"fullImage": "image",
"index": 0
},
{
"title": "Titel",
@ -31,68 +35,70 @@ class sellingTable extends HTMLElement {
"linkText": "Anzeige ansehen",
"target": "_blank"
},
]
];
super();
this.generateTable();
}
async generateTable() {
const table = document.createElement("table");
this.appendChild(table);
const tr = document.createElement("tr");
table.appendChild(tr);
config.forEach(element => {
this.config.forEach(element => {
const th = document.createElement("th");
th.innerText = element["title"];
tr.appendChild(th);
});
let xhr = new XMLHttpRequest();
xhr.onreadystatechange = () => {
if(xhr.readyState === 4 && xhr.status === 200){
const response = JSON.parse(xhr.responseText);
response.forEach( ad => {
const tr = document.createElement("tr");
table.appendChild(tr);
config.forEach(element => {
const th = document.createElement("th");
var graphql = JSON.stringify({
query: 'query { ebayKleinanzeigen(imageCount: 1) { elements { images { preview image } title price shipping link }}}',
})
var requestOptions = {
method: 'POST',
body: graphql,
};
let elements = (await (await fetch("http://localhost:1234/API/graphql.php", requestOptions)).json()).data.ebayKleinanzeigen.elements;
elements.forEach(ad => {
const tr = document.createElement("tr");
table.appendChild(tr);
this.config.forEach(element => {
const th = document.createElement("th");
switch(element["displayType"]) {
case "text":
th.innerText = ad[element["fieldName"]];
break;
case "link":
const link = document.createElement("a");
th.appendChild(link);
link.href = ad[element["fieldName"]];
link.innerText = element["linkText"];
if("target" in element) {
link.target = element["target"];
}
break;
case "image":
const img = document.createElement("img");
th.appendChild(img);
img.src = ad[element["fieldName"]];
img.onclick = () => {
const instance = basicLightbox.create(`
<img src="${ad[element["fullImage"]]}">
`);
instance.show();
}
break;
switch (element["displayType"]) {
case "text":
th.innerText = ad[element["fieldName"]];
break;
case "link":
const link = document.createElement("a");
th.appendChild(link);
link.href = ad[element["fieldName"]];
link.innerText = element["linkText"];
if ("target" in element) {
link.target = element["target"];
}
break;
case "image":
const img = document.createElement("img");
th.appendChild(img);
img.src = ad["images"][element["index"]][element["fieldName"]];
img.onclick = () => {
const instance = basicLightbox.create(`
<img src="${ad["images"][element["index"]][element["fullImage"]]}">
`);
instance.show();
}
break;
tr.appendChild(th);
});
})
}
}
}
xhr.open("GET", "/API/ebk.php");
xhr.send();
tr.appendChild(th);
});
});
}
}

View file

@ -1,19 +1,26 @@
class Skill extends HTMLElement {
constructor() {
super();
let xhr = new XMLHttpRequest();
xhr.onreadystatechange = () => {
if (xhr.readyState == 4 && xhr.status == 200) {
JSON.parse(xhr.responseText).forEach(skill => {
const image = document.createElement("img");
image.classList.add("skills");
image.src = "/API/getFile.php?filename=" + skill;
this.appendChild(image);
});
}
}
xhr.open("GET", "/API/skills.php");
xhr.send();
this.getSkills();
}
async getSkills(){
var graphql = JSON.stringify({
query: "query {skills}"
})
var requestOptions = {
method: 'POST',
body: graphql,
};
let skills = (await (await fetch("/API/graphql.php", requestOptions)).json()).data.skills;
skills.forEach(skill => {
const image = document.createElement("img");
image.classList.add("skills");
image.src = "/API/getFile.php?filename=" + skill;
this.appendChild(image);
});
}
}

View file

@ -26,7 +26,17 @@ async function loadPost() {
if(id == null) {
content.innerHTML = "<h1>404 - Post not found</h1>";
} else {
let post = await (await fetch("/API/getPost.php?id=" + id)).json();
var graphql = JSON.stringify({
query: 'query($postID: String!) {blogPost(id: $postID) {content title}}',
variables: {
"postID": id
}
})
var requestOptions = {
method: 'POST',
body: graphql,
};
let post = (await (await fetch("http://localhost:1234/API/graphql.php", requestOptions)).json()).data.blogPost;
content.innerHTML = post["content"];
document.title = post["title"] + " - Jonas Leder";

View file

@ -6,7 +6,7 @@
"author": "jonasled <git@jonasled.de>",
"license": "GPL-3.0-or-later",
"scripts": {
"compile": "concurrently \"yarn css\" \"yarn js\"",
"build": "concurrently \"yarn css\" \"yarn js\"",
"css": "stylus styl/ -o public/css/ ",
"js": "webpack --config ./webpack.conf.js",
"watch": "concurrently \"stylus -w styl/ -o public/css/\" \"cd public && php -S 0.0.0.0:1234\" \"webpack --config ./webpack.conf.js --mode development --watch\""

View file

@ -1,12 +0,0 @@
<?php
require "./lib/config.php";
$configValue = $_GET['name'];
switch ($configValue){
case "sitekey":
echo($sitekey);
break;
default:
echo("notFound");
}

View file

@ -1,62 +0,0 @@
<?php
require 'vendor/autoload.php';
require "./lib/config.php";
use GuzzleHttp\Client;
$responseJSON = [];
$client = new Client();
$headers = [
'authorization' => 'Basic ' . $ebayKleinanzeigenToken,
'user-agent' => 'okhttp/4.9.1',
'x-ebayk-app' => '4e10d7fd-6fef-4f87-afb0-b8ede2f494071636475109828',
'Host' => 'api.ebay-kleinanzeigen.de',
'Accept' => '*/*',
'Accept-Encoding' => 'gzip, deflate, br'
];
$response = $client->request('GET', "https://api.ebay-kleinanzeigen.de/api/ads.json?_in=title,price,pictures,link,features-active,search-distance,negotiation-enabled,attributes,medias,medias.media,medias.media.title,medias.media.media-link,store-id,store-title&page=0&size=31&userIds=$ebayKleinanzeigenUserId&pictureRequired=false&includeTopAds=false&limitTotalResultCount=true", [
'headers' => $headers ]);
$response = json_decode($response->getBody(), true);
$ads = $response["{http://www.ebayclassifiedsgroup.com/schema/ad/v1}ads"]["value"]["ad"];
foreach($ads as $ad) {
$element = [
"title" => $ad["title"]["value"],
"price" => $ad["price"]["amount"]["value"] . "",
"shipping" => "nein"
];
foreach($ad["attributes"]["attribute"] as $attribute) {
if(str_contains($attribute["name"], "versand")) {
$element["shipping"] = $attribute["value"][0]["value"];
}
}
foreach($ad["link"] as $link) {
if($link["rel"] == "self-public-website") {
$element["link"] = $link["href"];
}
}
if(sizeof($ad["pictures"]["picture"]) > 0) {
foreach($ad["pictures"]["picture"][0]["link"] as $picture) {
if($picture["rel"] == "teaser") {
$element["previewImage"] = str_replace("https://i.ebayimg.com", "/API/ebayimg.php?url=", $picture["href"]);
}
if($picture["rel"] == "XXL") {
$element["image"] = str_replace("https://i.ebayimg.com", "/API/ebayimg.php?url=", $picture["href"]);
}
}
}
array_push($responseJSON, $element);
}
if(isset($_GET["count"])) {
echo sizeof($responseJSON);
die();
}
echo json_encode($responseJSON);

View file

@ -1,29 +0,0 @@
<?php
include "./lib/config.php";
include "./lib/mysql.php";
$position = $_GET['position'];
if($position == "index"){
$limit = $homeMaxPost;
} else if($position == "footer"){
$limit = $footerMaxPost;
} else {
die("wrong parameter");
}
$responseJSON = [];
$result = $conn->query("SELECT * FROM posts order by id desc limit $limit");
if ($result->num_rows > 0) {
while ($row = $result->fetch_assoc()) {
$blogElement = [
"title" => $row["title"],
"id" => $row["id"],
"content" => $row["content"]
];
array_push($responseJSON, $blogElement);
}
}
header('Content-Type: application/json');
echo json_encode($responseJSON);

View file

@ -1,22 +0,0 @@
<?php
include("./lib/config.php");
require("./vendor/autoload.php");
use GuzzleHttp\Client;
$data = array(
'secret' => $secretkey,
'response' => $_POST['h-captcha-response']
);
$client = new Client();
$response = $client->post("https://hcaptcha.com/siteverify", [
"form_params" => $data
]);
$responseData = json_decode($response->getBody());
if($responseData->success) {
echo("$contactmail");
} else {
echo("Failed to verify Captcha");
}

View file

@ -1,24 +0,0 @@
<?php
include "./lib/config.php";
include "./lib/mysql.php";
$id = $conn->real_escape_string($_GET["id"]);
$result = $conn->query("SELECT * FROM posts WHERE id=$id");
if ($result->num_rows > 0) {
$row = $result->fetch_assoc();
} else {
die("Post not found");
}
$title = $row["title"];
$content = $row["content"];
$date = $row["date"];
$id = $row["id"];
header('Content-Type: application/json');
echo json_encode([
"title" => $title,
"content" => $content,
"date" => $date,
"id" => $id
]);

35
public/API/graphql.php Normal file
View file

@ -0,0 +1,35 @@
<?php
use GraphQL\GraphQL;
use GraphQL\Type\Schema;
require 'vendor/autoload.php';
require "./lib/config.php";
require "./lib/mysql.php";
require "./queries/queries.php";
$schema = new Schema([
'query' => $queryType
]);
$rawInput = file_get_contents('php://input');
$input = json_decode($rawInput, true);
$query = $input['query'];
$variableValues = isset($input['variables']) ? $input['variables'] : null;
try {
$rootValue = [
"db"=> $conn
];
$result = GraphQL::executeQuery($schema, $query, $rootValue, null, $variableValues);
$output = $result->toArray();
} catch (\Exception $e) {
$output = [
'errors' => [
[
'message' => $e->getMessage()
]
]
];
}
header('Content-Type: application/json');
echo json_encode($output);

View file

@ -1,39 +0,0 @@
<?php
require './vendor/autoload.php';
include("./lib/config.php");
include("./lib/mysql.php");
use GuzzleHttp\Client;
$data = array(
'secret' => $secretkey,
'response' => $_POST['h-captcha-response']
);
$client = new Client();
$response = $client->post("https://hcaptcha.com/siteverify", [
"form_params" => $data
]);
$responseData = json_decode($response->getBody());
if($responseData->success) {
$article =$conn->escape_string($_POST["pagename"]);
$name = $conn->escape_string($_POST["name"]);
$email = $conn->escape_string($_POST["email"]);
$comment = $conn->escape_string($_POST["comment"]);
$sql = "INSERT INTO comments (name, email, comment, article) VALUES ('$name', '$email', '$comment', '$article')";
if ($conn->query($sql) === TRUE) {
header("Location: " . $_SERVER["HTTP_REFERER"]);
} else {
echo "Error: " . $sql . "<br>" . $conn->error;
}
} else {
echo "Failed to verify captcha.";
}

View file

@ -1,23 +0,0 @@
<?php
include "./lib/config.php";
include "./lib/mysql.php";
include "./lib/getGravatar.php";
$article = $conn->real_escape_string($_GET["article"]);
$responseJSON = [];
$result = $conn->query("SELECT * FROM comments WHERE article='$article'");
if ($result->num_rows > 0) {
while ($row = $result->fetch_assoc()) {
$commentElement = [
"name" => $row["name"],
"comment" => $row["comment"],
"gravatarURL" => get_gravatar($row["email"])
];
array_push($responseJSON, $commentElement);
}
}
header('Content-Type: application/json');
echo json_encode($responseJSON);

View file

@ -0,0 +1,65 @@
<?php
use GraphQL\Type\Definition\Type;
use GraphQL\Type\Definition\ObjectType;
$blogPostFields = new ObjectType([
"name" => "Blog",
"fields" => [
"title" => Type::string(),
"content" => Type::string(),
"date" => Type::string(),
"id" => Type::string()
],
]);
function blogPost($id, $conn)
{
$id = $conn->real_escape_string($id);
$result = $conn->query("SELECT * FROM posts WHERE id=$id");
if ($result->num_rows > 0) {
$row = $result->fetch_assoc();
} else {
return [
"title" => "Nicht Gefunden",
"content" => "Post wurde nicht gefunden",
"date" => "2000-01-01 00:00:00",
"id" => "-1"
];
}
return [
"title" => $row["title"],
"content" => $row["content"],
"date" => $row["date"],
"id" => $row["id"],
];
}
function blogPosts($count, $contentLength, $conn)
{
$response = [];
$result = $conn->query("SELECT * FROM posts order by id desc limit $count");
if ($result->num_rows > 0) {
while ($row = $result->fetch_assoc()) {
$content = $row["content"];
if($contentLength != null && strlen($content) > $contentLength) {
$contentNew = substr($content, 0, $contentLength);
$contentRest = substr($content, $contentLength);
$content = $contentNew . explode(" ", $contentRest)[0] . " ...";
}
$blogElement = [
"title" => $row["title"],
"content" => $content,
"date" => $row["date"],
"id" => $row["id"],
];
array_push($response, $blogElement);
}
}
return $response;
}

View file

@ -0,0 +1,65 @@
<?php
use GraphQL\Type\Definition\Type;
use GraphQL\Type\Definition\ObjectType;
use GuzzleHttp\Client;
include "lib/getGravatar.php";
$commentField = new ObjectType([
"name" => "Comment",
"fields" => [
"name" => Type::string(),
"comment" => Type::string(),
"gravatarURL" => Type::string(),
"id" => Type::int()
],
]);
function comments($article, $conn)
{
$response = [];
$result = $conn->query("SELECT * FROM comments WHERE article='$article'");
while ($row = $result->fetch_assoc()) {
$commentElement = [
"name" => $row["name"],
"comment" => $row["comment"],
"gravatarURL" => get_gravatar($row["email"]),
"id" => $row["id"]
];
array_push($response, $commentElement);
}
return $response;
}
function newComment($conn, $article, $name, $email, $comment, $hCaptchaResponse)
{
require "./lib/config.php";
$data = array(
'secret' => $secretkey,
'response' => $hCaptchaResponse
);
$client = new Client();
$response = $client->post("https://hcaptcha.com/siteverify", [
"form_params" => $data
]);
$responseData = json_decode($response->getBody());
if (!$responseData->success) {
return "Failed to verify Captcha";
}
$article = $conn->escape_string($article);
$name = $conn->escape_string($name);
$email = $conn->escape_string($email);
$comment = $conn->escape_string($comment);
$sql = "INSERT INTO comments (name, email, comment, article) VALUES ('$name', '$email', '$comment', '$article')";
if ($conn->query($sql) === TRUE) {
return "OK";
} else {
return "Error: " . $sql . "<br>" . $conn->error;
}
}

View file

@ -0,0 +1,103 @@
<?php
use GraphQL\Type\Definition\Type;
use GraphQL\Type\Definition\ObjectType;
use GuzzleHttp\Client;
$ebayKleinanzeigenImages = new ObjectType([
"name" => "EBK Image",
"fields" => [
"preview" => Type::string(),
"image" => Type::string()
]
]);
$ebayKleinanzeigenElements = new ObjectType([
"name" => "EBK Elements",
"fields" => [
"title" => Type::string(),
"price" => Type::string(),
"shipping" => Type::string(),
"link" => Type::string(),
"images" => [
"type" => Type::listOf($ebayKleinanzeigenImages),
"args" => [
"count" => Type::int()
]
],
"id" => Type::string()
]
]);
$ebayKleinanzeigenFields = new ObjectType([
"name" => "Ebay Kleinanzeigen",
"fields" => [
"count" => Type::int(),
"elements" => Type::listOf($ebayKleinanzeigenElements)
],
]);
function ebayKleinanzeigen($imageCount) {
require "./lib/config.php";
$elements = [];
$client = new Client();
$headers = [
'authorization' => 'Basic ' . $ebayKleinanzeigenToken,
'user-agent' => 'okhttp/4.9.1',
'x-ebayk-app' => '4e10d7fd-6fef-4f87-afb0-b8ede2f494071636475109828',
'Host' => 'api.ebay-kleinanzeigen.de',
'Accept' => '*/*',
'Accept-Encoding' => 'gzip, deflate, br'
];
$response = $client->request('GET', "https://api.ebay-kleinanzeigen.de/api/ads.json?_in=title,price,pictures,link,features-active,search-distance,negotiation-enabled,attributes,medias,medias.media,medias.media.title,medias.media.media-link,store-id,store-title&page=0&size=31&userIds=$ebayKleinanzeigenUserId&pictureRequired=false&includeTopAds=false&limitTotalResultCount=true", [
'headers' => $headers ]);
$response = json_decode($response->getBody(), true);
$ads = $response["{http://www.ebayclassifiedsgroup.com/schema/ad/v1}ads"]["value"]["ad"];
foreach($ads as $ad) {
$element = [
"title" => html_entity_decode($ad["title"]["value"]),
"id" => $ad["id"],
"price" => $ad["price"]["amount"]["value"] . "",
"shipping" => "nein"
];
foreach($ad["attributes"]["attribute"] as $attribute) {
if(str_contains($attribute["name"], "versand")) {
$element["shipping"] = $attribute["value"][0]["value"];
}
}
foreach($ad["link"] as $link) {
if($link["rel"] == "self-public-website") {
$element["link"] = $link["href"];
}
}
$images = [];
foreach(array_slice($ad["pictures"]["picture"], 0, $imageCount) as $picture) {
$image = [];
foreach($picture["link"] as $pictureSize) {
if($pictureSize["rel"] == "teaser") {
$image["preview"] = str_replace("https://i.ebayimg.com", "/API/ebayimg.php?url=", $pictureSize["href"]);
}
if($pictureSize["rel"] == "XXL") {
$image["image"] = str_replace("https://i.ebayimg.com", "/API/ebayimg.php?url=", $pictureSize["href"]);
}
}
array_push($images, $image);
}
$element["images"] = $images;
array_push($elements, $element);
}
return [
"count" => sizeof($elements),
"elements" => $elements
];
}

View file

@ -0,0 +1,22 @@
<?php
use GuzzleHttp\Client;
function mailAddress($hCaptchaResponse) {
require "./lib/config.php";
$data = array(
'secret' => $secretkey,
'response' => $hCaptchaResponse
);
$client = new Client();
$response = $client->post("https://hcaptcha.com/siteverify", [
"form_params" => $data
]);
$responseData = json_decode($response->getBody());
if($responseData->success) {
return "$contactmail";
} else {
return "Failed to verify Captcha";
}
}

View file

@ -0,0 +1,79 @@
<?php
use GraphQL\Type\Definition\ObjectType;
use GraphQL\Type\Definition\Type;
require "./queries/skills.php";
require "./queries/blogPost.php";
require "./queries/comments.php";
require "./queries/mailAddress.php";
require "./queries/ebayKleinanzeigen.php";
$queryType = new ObjectType([
'name' => 'Query',
'fields' => [
'sitekey' => [
'type' => Type::string(),
'resolve' => fn ($rootValue, $args) => $sitekey,
],
'mailAddress' => [
'type' => Type::string(),
"args" => [
"hCaptchaResponse" => Type::string()
],
'resolve' => fn ($rootValue, $args) => mailAddress($args["hCaptchaResponse"]),
],
'skills' => [
'type' => Type::listOf(Type::string()),
'resolve' => fn ($rootValue, $args) => getSkills(),
],
'blogPost' => [
"type" => $blogPostFields,
'args' => [
'id' => Type::nonNull(Type::string()),
],
'resolve' => fn ($rootValue, $args) => blogPost($args["id"], $rootValue["db"]),
],
'blogPosts' => [
"type" => Type::listOf($blogPostFields),
"args" => [
"count" => Type::nonNull(Type::int()),
"contentLength" => [
"type" => Type::int(),
"defaultValue" => null
]
],
'resolve' => fn ($rootValue, $args) => blogPosts($args["count"], $args["contentLength"], $rootValue["db"]),
],
'comments' => [
"type" => Type::listOf($commentField),
"args" => [
"article" => Type::nonNull(Type::string()),
],
'resolve' => fn ($rootValue, $args) => comments($args["article"], $rootValue["db"]),
],
"newComment" => [
"type" => Type::string(),
"args" => [
"article" => Type::string(),
"name" => Type::string(),
"email" => Type::string(),
"comment" => Type::string(),
"hCaptchaResponse" => Type::string()
],
'resolve' => fn ($rootValue, $args) => newComment($rootValue["db"], $args["article"], $args["name"], $args["email"], $args["comment"], $args["hCaptchaResponse"]),
],
'ebayKleinanzeigen' => [
"type" => $ebayKleinanzeigenFields,
"args" => [
"imageCount" => [
"type" => Type::int(),
"defaultValue" => 0
]
],
'resolve' => fn ($rootValue, $args) => ebayKleinanzeigen($args["imageCount"]),
]
],
]);

View file

@ -0,0 +1,23 @@
<?php
function getSkills() {
require "./lib/config.php";
$s3Client = new Aws\S3\S3Client([
'version' => 'latest',
'region' => 'us-east-1',
'endpoint' => $S3Server,
'use_path_style_endpoint' => true,
'credentials' => [
'key' => $S3AccessKey,
'secret' => $S3SecretKey,
],
]);
$result = $s3Client->ListObjects(['Bucket' => $S3BucketName, 'Delimiter'=>'/', 'Prefix' => 'skills/']);
$response = [];
foreach ($result["Contents"] as $skill){
array_push($response, $skill["Key"]);
}
return $response;
}

View file

@ -1,24 +0,0 @@
<?php
include("./lib/config.php");
require 'vendor/autoload.php';
$s3Client = new Aws\S3\S3Client([
'version' => 'latest',
'region' => 'us-east-1',
'endpoint' => $S3Server,
'use_path_style_endpoint' => true,
'credentials' => [
'key' => $S3AccessKey,
'secret' => $S3SecretKey,
],
]);
$result = $s3Client->ListObjects(['Bucket' => $S3BucketName, 'Delimiter'=>'/', 'Prefix' => 'skills/']);
$response = [];
foreach ($result["Contents"] as $skill){
array_push($response, $skill["Key"]);
}
header("Content-Type: application/json");
echo json_encode($response);

View file

@ -49,20 +49,24 @@
<a href="https://hcaptcha.com/privacy">Privacy Policy</a> and
<a href="https://hcaptcha.com/terms">Terms of Service</a> apply.
<script type="text/javascript">
function onSubmit(token) {
let xmlhttp = new XMLHttpRequest();
xmlhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
let button = document.getElementById("emailButton");
let emailElement = document.createElement("p");
emailElement.className = "emailBox";
emailElement.innerText = this.responseText;
button.parentNode.replaceChild(emailElement, button);
}
async function onSubmit(token) {
var graphql = JSON.stringify({
query: 'query($hCaptchaResponse: String!) { mailAddress(hCaptchaResponse: $hCaptchaResponse)}',
variables: {
"hCaptchaResponse": token
}
})
var requestOptions = {
method: 'POST',
body: graphql,
};
xmlhttp.open("POST", "/API/getMail.php", true);
xmlhttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
xmlhttp.send("h-captcha-response=" + token);
let mailAddress = (await (await fetch("http://localhost:1234/API/graphql.php", requestOptions)).json()).data.mailAddress;
let button = document.getElementById("emailButton");
let emailElement = document.createElement("p");
emailElement.className = "emailBox";
emailElement.innerText = mailAddress;
button.parentNode.replaceChild(emailElement, button);
}
</script>
</div>