From 634d0061d46fc6492ab698ce77a581fb54615509 Mon Sep 17 00:00:00 2001 From: Marcin Kurczewski Date: Sat, 17 May 2014 11:45:27 +0200 Subject: [PATCH] Added API documentation prototype --- public_html/media/css/static-api.css | 5 + src/Api/Api.php | 5 + src/Api/JobArgs/JobArgs.php | 10 ++ src/Api/Jobs/AbstractJob.php | 11 ++ src/Api/Jobs/PostJobs/AddPostJob.php | 7 +- src/Api/Jobs/PostJobs/EditPostJob.php | 18 ++- src/Api/Jobs/UserJobs/AddUserJob.php | 7 +- src/Api/Jobs/UserJobs/EditUserJob.php | 16 +-- src/Controllers/StaticPagesController.php | 5 + src/Views/layout-normal.phtml | 3 +- src/Views/static/static-api.phtml | 141 ++++++++++++++++++++++ src/routes.php | 1 + 12 files changed, 205 insertions(+), 24 deletions(-) create mode 100644 public_html/media/css/static-api.css create mode 100644 src/Views/static/static-api.phtml diff --git a/public_html/media/css/static-api.css b/public_html/media/css/static-api.css new file mode 100644 index 00000000..f3ac8d7b --- /dev/null +++ b/public_html/media/css/static-api.css @@ -0,0 +1,5 @@ +pre { + background: ghostwhite; + padding: 0.5em; + border-left: 0.2em solid silver; +} diff --git a/src/Api/Api.php b/src/Api/Api.php index 05fe4fd2..03419e5c 100644 --- a/src/Api/Api.php +++ b/src/Api/Api.php @@ -1,6 +1,11 @@ subJobs []= $subJob; + } + + public function getSubJobs() + { + return $this->subJobs; + } + public function getRequiredPrivileges() { return false; diff --git a/src/Api/Jobs/PostJobs/AddPostJob.php b/src/Api/Jobs/PostJobs/AddPostJob.php index 70013921..017e1371 100644 --- a/src/Api/Jobs/PostJobs/AddPostJob.php +++ b/src/Api/Jobs/PostJobs/AddPostJob.php @@ -1,6 +1,11 @@ addSubJob(new EditPostJob()); + } + public function execute() { $post = PostModel::spawn(); @@ -20,7 +25,7 @@ class AddPostJob extends AbstractJob Logger::bufferChanges(); try { - $job = new EditPostJob(); + $job = $this->getSubJobs()[0]; $job->setContext(AbstractJob::CONTEXT_BATCH_ADD); Api::run($job, $arguments); } diff --git a/src/Api/Jobs/PostJobs/EditPostJob.php b/src/Api/Jobs/PostJobs/EditPostJob.php index 3c24662d..bf68e2ae 100644 --- a/src/Api/Jobs/PostJobs/EditPostJob.php +++ b/src/Api/Jobs/PostJobs/EditPostJob.php @@ -6,6 +6,12 @@ class EditPostJob extends AbstractJob public function __construct() { $this->postRetriever = new PostRetriever($this); + $this->addSubJob(new EditPostSafetyJob()); + $this->addSubJob(new EditPostTagsJob()); + $this->addSubJob(new EditPostSourceJob()); + $this->addSubJob(new EditPostRelationsJob()); + $this->addSubJob(new EditPostContentJob()); + $this->addSubJob(new EditPostThumbJob()); } public function execute() @@ -14,17 +20,7 @@ class EditPostJob extends AbstractJob Logger::bufferChanges(); - $subJobs = - [ - new EditPostSafetyJob(), - new EditPostTagsJob(), - new EditPostSourceJob(), - new EditPostRelationsJob(), - new EditPostContentJob(), - new EditPostThumbJob(), - ]; - - foreach ($subJobs as $subJob) + foreach ($this->getSubJobs() as $subJob) { $subJob->setContext($this->getContext() == self::CONTEXT_BATCH_ADD ? self::CONTEXT_BATCH_ADD diff --git a/src/Api/Jobs/UserJobs/AddUserJob.php b/src/Api/Jobs/UserJobs/AddUserJob.php index bc36172c..b4029563 100644 --- a/src/Api/Jobs/UserJobs/AddUserJob.php +++ b/src/Api/Jobs/UserJobs/AddUserJob.php @@ -1,6 +1,11 @@ addSubJob(new EditUserJob()); + } + public function execute() { $firstUser = UserModel::getCount() == 0; @@ -25,7 +30,7 @@ class AddUserJob extends AbstractJob Logger::bufferChanges(); try { - $job = new EditUserJob(); + $job = $this->getSubJobs()[0]; $job->setContext(self::CONTEXT_BATCH_ADD); Api::run($job, $arguments); } diff --git a/src/Api/Jobs/UserJobs/EditUserJob.php b/src/Api/Jobs/UserJobs/EditUserJob.php index ed494e49..cd2dd555 100644 --- a/src/Api/Jobs/UserJobs/EditUserJob.php +++ b/src/Api/Jobs/UserJobs/EditUserJob.php @@ -2,24 +2,20 @@ class EditUserJob extends AbstractJob { protected $userRetriever; - protected $subJobs; public function __construct() { $this->userRetriever = new UserRetriever($this); - $this->subJobs = - [ - new EditUserAccessRankJob(), - new EditUserNameJob(), - new EditUserPasswordJob(), - new EditUserEmailJob(), - ]; + $this->addSubJob(new EditUserAccessRankJob()); + $this->addSubJob(new EditUserNameJob()); + $this->addSubJob(new EditUserPasswordJob()); + $this->addSubJob(new EditUserEmailJob()); } public function canEditAnything($user) { $this->privileges = []; - foreach ($this->subJobs as $subJob) + foreach ($this->getSubJobs() as $subJob) { try { @@ -40,7 +36,7 @@ class EditUserJob extends AbstractJob Logger::bufferChanges(); - foreach ($this->subJobs as $subJob) + foreach ($this->getSubJobs() as $subJob) { $subJob->setContext($this->getContext() == self::CONTEXT_BATCH_ADD ? self::CONTEXT_BATCH_ADD diff --git a/src/Controllers/StaticPagesController.php b/src/Controllers/StaticPagesController.php index c50e6f92..be3b91b9 100644 --- a/src/Controllers/StaticPagesController.php +++ b/src/Controllers/StaticPagesController.php @@ -38,6 +38,11 @@ class StaticPagesController extends AbstractController $this->renderView('static-help'); } + public function apiDocsView() + { + $this->renderView('static-api'); + } + public function fatalErrorView($code = null) { throw new SimpleException('Error ' . $code . ' while retrieving ' . $_SERVER['REQUEST_URI']); diff --git a/src/Views/layout-normal.phtml b/src/Views/layout-normal.phtml index 879a3305..3e4c671a 100644 --- a/src/Views/layout-normal.phtml +++ b/src/Views/layout-normal.phtml @@ -42,9 +42,10 @@ $this->assets->addScript('core.js');
- szurubooru  + + API Logs diff --git a/src/Views/static/static-api.phtml b/src/Views/static/static-api.phtml new file mode 100644 index 00000000..3342a362 --- /dev/null +++ b/src/Views/static/static-api.phtml @@ -0,0 +1,141 @@ +assets->addStylesheet('static-api.css'); +?> + +

API documentation

+ +

All interaction with API proceeds through just one URL: .

+ +

One request to API means executing one so-called „job”. Most of things that can be done through web +interface, can be also done through the API.

+ +
+ +

Request construction

+ +

To specify job to be executed, send name parameter. Optional job arguments can be specified with +args parameter. Example using curl:

+ +
curl \
+	--data 'name=get-post' \
+		'&args[post-id]=5408' \
+	
+ +

Authentication

+ +

In order to make authenticated request, you need to supply request with your credentials. This can be done by +passing auth[user] and auth[name] parameters:

+ +
curl \
+	--data 'auth[user]=example' \
+		'&auth[pass]=secret' \
+		'&name=get-post' \
+		'&args[post-id]=5408' \
+	
+ +

Sending files

+ +

In order to send files to API, you have to send multipart/form-data request. With curl +this can be done using -F option to encode each parameter and prepending @ character to +chosen file name:

+ +
curl \
+	-F 'auth[user]=example' \
+	-F 'auth[pass]=secret' \
+	-F 'name=add-post' \
+	-F 'args[new-tag-names][0]=test' \
+	-F 'args[new-tag-names][1]=test2' \
+	-F 'args[new-tag-names][2]=test3' \
+	-F 'args[new-post-content]=@./custom.png' \
+	
+ +

Output

+ +

Output is always represented in JSON array. Files are stored in JSON as well using gzip compression and base64 +encoding.

+ +

Handling errors

+ +

When errors occur all errors are logged to message field and changes done with request is rolled +back.

+ +
+ +

Privilege table

+ +

Each job checks for some privileges depending on context it is run with.

+ + + + + + + + + + privileges as $privilege => $minAccessRank): ?> + + + + + + +
PrivilegeMinimum access rank
+ +
+ +

Full list of available jobs

+ + + +

+ getName() ?> +

+ + args))) . ')'; + } + elseif ($args instanceof JobArgsAlternative) + { + return '(' . implode(' OR ', array_filter(array_map(function($arg) use ($showArgs) + { + return $showArgs($arg); + }, $args->args))) . ')'; + } + elseif ($args instanceof JobArgsOptional) + return $showArgs($args->args[0]) . ' (optional)'; + elseif (in_array($args, JobArgs::getInternalArguments())) + return null; + else + return $args; + }; + ?> + +

Required arguments: getRequiredArguments()) ?>

+

Requires e-mail confirmation: isConfirmedEmailRequired() ? 'yes' : 'no' ?>

+

Requires authentication: isAuthenticationRequired() ? 'yes' : 'no' ?>

+ getSubJobs())): ?> +

Sub jobs: getName() . '">' . $job->getName() . ''; + }, $job->getSubJobs())); ?>

+ + +
+ diff --git a/src/routes.php b/src/routes.php index c38346ba..f856aefa 100644 --- a/src/routes.php +++ b/src/routes.php @@ -3,6 +3,7 @@ \Chibi\Router::register(['StaticPagesController', 'mainPageView'], 'GET', ''); \Chibi\Router::register(['StaticPagesController', 'mainPageView'], 'GET', '/index'); +\Chibi\Router::register(['StaticPagesController', 'apiDocsView'], 'GET', '/api-docs'); \Chibi\Router::register(['StaticPagesController', 'helpView'], 'GET', '/help'); \Chibi\Router::register(['StaticPagesController', 'helpView'], 'GET', '/help/{tab}'); \Chibi\Router::register(['StaticPagesController', 'fatalErrorView'], 'POST', '/fatal-error/{code}');