mirror of
https://code.mensbeam.com/MensBeam/Arsse.git
synced 2024-12-23 09:02:41 +00:00
929d763981
The type parameters of Db\Driver::prepare() and the parameters of Db\Statement::run() can now be arrays, which will be iterated over recursively to bind scalar values to the SQL statement. This simplifies the construction of arbitrary UPDATE statements (the WHERE clause no longer needs to be taken into account) and should make it clearer what is happening in these cases. It should also simplify the creation of IN() clauses down the road if they become necessary.
163 lines
No EOL
6.8 KiB
PHP
163 lines
No EOL
6.8 KiB
PHP
<?php
|
|
declare(strict_types=1);
|
|
namespace JKingWeb\Arsse\REST\NextCloudNews;
|
|
use JKingWeb\Arsse\Data;
|
|
use JKingWeb\Arsse\AbstractException;
|
|
use JKingWeb\Arsse\Db\ExceptionInput;
|
|
use JKingWeb\Arsse\REST\Response;
|
|
|
|
class V1_2 extends \JKingWeb\Arsse\REST\AbstractHandler {
|
|
function __construct() {
|
|
}
|
|
|
|
function dispatch(\JKingWeb\Arsse\REST\Request $req): Response {
|
|
// try to authenticate
|
|
if(!Data::$user->authHTTP()) return new Response(401, "", "", ['WWW-Authenticate: Basic realm="NextCloud News API v1-2"']);
|
|
// only accept GET, POST, PUT, or DELETE
|
|
if(!in_array($req->method, ["GET", "POST", "PUT", "DELETE"])) return new Response(405, "", "", ['Allow: GET, POST, PUT, DELETE']);
|
|
// normalize the input
|
|
if($req->body) {
|
|
// if the entity body is not JSON according to content type, return "415 Unsupported Media Type"
|
|
if(!preg_match("<^application/json\b|^$>", $req->type)) return new Response(415, "", "", ['Accept: application/json']);
|
|
try {
|
|
$data = json_decode($req->body, true);
|
|
} catch(\Throwable $e) {
|
|
// if the body could not be parsed as JSON, return "400 Bad Request"
|
|
return new Response(400);
|
|
}
|
|
} else {
|
|
$data = [];
|
|
}
|
|
// FIXME: Do query parameters take precedence in NextCloud? Is there a conflict error when values differ?
|
|
$data = array_merge($data, $req->query);
|
|
// match the path
|
|
if(preg_match("<^/(items|folders|feeds|cleanup|version|status|user)(?:/([^/]+))?(?:/([^/]+))?(?:/([^/]+))?/?$>", $req->path, $url)) {
|
|
// clean up the path
|
|
$scope = $url[1];
|
|
unset($url[0]);
|
|
unset($url[1]);
|
|
$url = array_filter($url);
|
|
$url = array_values($url);
|
|
// check to make sure the requested function is implemented
|
|
$func = $scope.$req->method;
|
|
if(!method_exists($this, $func)) return new Response(501);
|
|
// dispatch
|
|
try {
|
|
return $this->$func($url, $data);
|
|
} catch(Exception $e) {
|
|
// if there was a REST exception return 400
|
|
return new Response(400);
|
|
} catch(AbstractException $e) {
|
|
// if there was any other Arsse exception return 500
|
|
return new Response(500);
|
|
}
|
|
} else {
|
|
return new Response(404);
|
|
}
|
|
}
|
|
|
|
// list folders
|
|
protected function foldersGET(array $url, array $data): Response {
|
|
// if URL is more than '/folders' this is an error
|
|
if(sizeof($url)==1) return new Response(405, "", "", ['Allow: PUT, DELETE']);
|
|
if(sizeof($url) > 1) return new Response(404);
|
|
$folders = Data::$db->folderList(Data::$user->id, null, false)->getAll();
|
|
return new Response(200, ['folders' => $folders]);
|
|
}
|
|
|
|
// create a folder
|
|
protected function foldersPOST(array $url, array $data): Response {
|
|
// if URL is more than '/folders' this is an error
|
|
if(sizeof($url)==1) return new Response(405, "", "", ['Allow: PUT, DELETE']);
|
|
if(sizeof($url) > 1) return new Response(404);
|
|
try {
|
|
$folder = Data::$db->folderAdd(Data::$user->id, $data);
|
|
} catch(ExceptionInput $e) {
|
|
switch($e->getCode()) {
|
|
// folder already exists
|
|
case 10236: return new Response(409);
|
|
// folder name not acceptable
|
|
case 10231:
|
|
case 10232: return new Response(422);
|
|
// other errors related to input
|
|
default: return new Response(400);
|
|
}
|
|
}
|
|
$folder = Data::$db->folderPropertiesGet(Data::$user->id, $folder);
|
|
return new Response(200, ['folders' => [$folder]]);
|
|
}
|
|
|
|
// delete a folder
|
|
protected function foldersDELETE(array $url, array $data): Response {
|
|
// if URL is more or less than '/folders/$id' this is an error
|
|
if(sizeof($url) < 1) return new Response(405, "", "", ['Allow: GET, POST']);
|
|
if(sizeof($url) > 1) return new Response(404);
|
|
// folder ID must be integer
|
|
if(strval(intval($url[0])) !== $url[0]) return new Response(404);
|
|
// perform the deletion
|
|
try {
|
|
Data::$db->folderRemove(Data::$user->id, (int) $url[0]);
|
|
} catch(ExceptionInput $e) {
|
|
// folder does not exist
|
|
return new Response(404);
|
|
}
|
|
return new Response(204);
|
|
}
|
|
|
|
// rename a folder (also supports moving nesting folders, but this is not a feature of the API)
|
|
protected function foldersPUT(array $url, array $data): Response {
|
|
// if URL is more or less than '/folders/$id' this is an error
|
|
if(sizeof($url) < 1) return new Response(405, "", "", ['Allow: GET, POST']);
|
|
if(sizeof($url) > 1) return new Response(404);
|
|
// folder ID must be integer
|
|
if(strval(intval($url[0])) !== $url[0]) return new Response(404);
|
|
// there must be some change to be made
|
|
if(!sizeof($data)) return new Response(422);
|
|
// perform the edit
|
|
try {
|
|
Data::$db->folderPropertiesSet(Data::$user->id, (int) $url[0], $data);
|
|
} catch(ExceptionInput $e) {
|
|
switch($e->getCode()) {
|
|
// folder does not exist
|
|
case 10235: return new Response(404);
|
|
// folder already exists
|
|
case 10236: return new Response(409);
|
|
// folder name not acceptable
|
|
case 10231:
|
|
case 10232: return new Response(422);
|
|
// other errors related to input
|
|
default: return new Response(400);
|
|
}
|
|
}
|
|
return new Response(204);
|
|
}
|
|
|
|
// return the server version
|
|
protected function versionGET(array $url, array $data): Response {
|
|
// if URL is more than '/version' this is an error
|
|
if(sizeof($url)) return new Response(404);
|
|
return new Response(200, ['version' => \JKingWeb\Arsse\VERSION]);
|
|
}
|
|
|
|
// invalid function
|
|
protected function versionPOST(array $url, array $data): Response {
|
|
// if URL is more than '/version' this is an error
|
|
if(sizeof($url)) return new Response(404);
|
|
return new Response(405, "", "", ['Allow: GET']);
|
|
}
|
|
|
|
// invalid function
|
|
protected function versionPUT(array $url, array $data): Response {
|
|
// if URL is more than '/version' this is an error
|
|
if(sizeof($url)) return new Response(404);
|
|
return new Response(405, "", "", ['Allow: GET']);
|
|
}
|
|
|
|
// invalid function
|
|
protected function versionDELETE(array $url, array $data): Response {
|
|
// if URL is more than '/version' this is an error
|
|
if(sizeof($url)) return new Response(404);
|
|
return new Response(405, "", "", ['Allow: GET']);
|
|
}
|
|
|
|
} |