aboutsummaryrefslogtreecommitdiffhomepage
path: root/application/api/controllers
diff options
context:
space:
mode:
Diffstat (limited to 'application/api/controllers')
-rw-r--r--application/api/controllers/ApiController.php19
-rw-r--r--application/api/controllers/History.php70
-rw-r--r--application/api/controllers/Links.php112
3 files changed, 199 insertions, 2 deletions
diff --git a/application/api/controllers/ApiController.php b/application/api/controllers/ApiController.php
index 1dd47f17..3be85b98 100644
--- a/application/api/controllers/ApiController.php
+++ b/application/api/controllers/ApiController.php
@@ -2,6 +2,7 @@
2 2
3namespace Shaarli\Api\Controllers; 3namespace Shaarli\Api\Controllers;
4 4
5use Shaarli\Config\ConfigManager;
5use \Slim\Container; 6use \Slim\Container;
6 7
7/** 8/**
@@ -19,7 +20,7 @@ abstract class ApiController
19 protected $ci; 20 protected $ci;
20 21
21 /** 22 /**
22 * @var \ConfigManager 23 * @var ConfigManager
23 */ 24 */
24 protected $conf; 25 protected $conf;
25 26
@@ -29,6 +30,11 @@ abstract class ApiController
29 protected $linkDb; 30 protected $linkDb;
30 31
31 /** 32 /**
33 * @var \History
34 */
35 protected $history;
36
37 /**
32 * @var int|null JSON style option. 38 * @var int|null JSON style option.
33 */ 39 */
34 protected $jsonStyle; 40 protected $jsonStyle;
@@ -45,10 +51,21 @@ abstract class ApiController
45 $this->ci = $ci; 51 $this->ci = $ci;
46 $this->conf = $ci->get('conf'); 52 $this->conf = $ci->get('conf');
47 $this->linkDb = $ci->get('db'); 53 $this->linkDb = $ci->get('db');
54 $this->history = $ci->get('history');
48 if ($this->conf->get('dev.debug', false)) { 55 if ($this->conf->get('dev.debug', false)) {
49 $this->jsonStyle = JSON_PRETTY_PRINT; 56 $this->jsonStyle = JSON_PRETTY_PRINT;
50 } else { 57 } else {
51 $this->jsonStyle = null; 58 $this->jsonStyle = null;
52 } 59 }
53 } 60 }
61
62 /**
63 * Get the container.
64 *
65 * @return Container
66 */
67 public function getCi()
68 {
69 return $this->ci;
70 }
54} 71}
diff --git a/application/api/controllers/History.php b/application/api/controllers/History.php
new file mode 100644
index 00000000..2ff9deaf
--- /dev/null
+++ b/application/api/controllers/History.php
@@ -0,0 +1,70 @@
1<?php
2
3
4namespace Shaarli\Api\Controllers;
5
6use Shaarli\Api\Exceptions\ApiBadParametersException;
7use Slim\Http\Request;
8use Slim\Http\Response;
9
10/**
11 * Class History
12 *
13 * REST API Controller: /history
14 *
15 * @package Shaarli\Api\Controllers
16 */
17class History extends ApiController
18{
19 /**
20 * Service providing operation regarding Shaarli datastore and settings.
21 *
22 * @param Request $request Slim request.
23 * @param Response $response Slim response.
24 *
25 * @return Response response.
26 *
27 * @throws ApiBadParametersException Invalid parameters.
28 */
29 public function getHistory($request, $response)
30 {
31 $history = $this->history->getHistory();
32
33 // Return history operations from the {offset}th, starting from {since}.
34 $since = \DateTime::createFromFormat(\DateTime::ATOM, $request->getParam('since'));
35 $offset = $request->getParam('offset');
36 if (empty($offset)) {
37 $offset = 0;
38 }
39 else if (ctype_digit($offset)) {
40 $offset = (int) $offset;
41 } else {
42 throw new ApiBadParametersException('Invalid offset');
43 }
44
45 // limit parameter is either a number of links or 'all' for everything.
46 $limit = $request->getParam('limit');
47 if (empty($limit)) {
48 $limit = count($history);
49 } else if (ctype_digit($limit)) {
50 $limit = (int) $limit;
51 } else {
52 throw new ApiBadParametersException('Invalid limit');
53 }
54
55 $out = [];
56 $i = 0;
57 foreach ($history as $entry) {
58 if ((! empty($since) && $entry['datetime'] <= $since) || count($out) >= $limit) {
59 break;
60 }
61 if (++$i > $offset) {
62 $out[$i] = $entry;
63 $out[$i]['datetime'] = $out[$i]['datetime']->format(\DateTime::ATOM);
64 }
65 }
66 $out = array_values($out);
67
68 return $response->withJson($out, 200, $this->jsonStyle);
69 }
70}
diff --git a/application/api/controllers/Links.php b/application/api/controllers/Links.php
index d4f1a09c..eb78dd26 100644
--- a/application/api/controllers/Links.php
+++ b/application/api/controllers/Links.php
@@ -97,11 +97,121 @@ class Links extends ApiController
97 */ 97 */
98 public function getLink($request, $response, $args) 98 public function getLink($request, $response, $args)
99 { 99 {
100 if (! isset($this->linkDb[$args['id']])) { 100 if (!isset($this->linkDb[$args['id']])) {
101 throw new ApiLinkNotFoundException(); 101 throw new ApiLinkNotFoundException();
102 } 102 }
103 $index = index_url($this->ci['environment']); 103 $index = index_url($this->ci['environment']);
104 $out = ApiUtils::formatLink($this->linkDb[$args['id']], $index); 104 $out = ApiUtils::formatLink($this->linkDb[$args['id']], $index);
105
105 return $response->withJson($out, 200, $this->jsonStyle); 106 return $response->withJson($out, 200, $this->jsonStyle);
106 } 107 }
108
109 /**
110 * Creates a new link from posted request body.
111 *
112 * @param Request $request Slim request.
113 * @param Response $response Slim response.
114 *
115 * @return Response response.
116 */
117 public function postLink($request, $response)
118 {
119 $data = $request->getParsedBody();
120 $link = ApiUtils::buildLinkFromRequest($data, $this->conf->get('privacy.default_private_links'));
121 // duplicate by URL, return 409 Conflict
122 if (! empty($link['url']) && ! empty($dup = $this->linkDb->getLinkFromUrl($link['url']))) {
123 return $response->withJson(
124 ApiUtils::formatLink($dup, index_url($this->ci['environment'])),
125 409,
126 $this->jsonStyle
127 );
128 }
129
130 $link['id'] = $this->linkDb->getNextId();
131 $link['shorturl'] = link_small_hash($link['created'], $link['id']);
132
133 // note: general relative URL
134 if (empty($link['url'])) {
135 $link['url'] = '?' . $link['shorturl'];
136 }
137
138 if (empty($link['title'])) {
139 $link['title'] = $link['url'];
140 }
141
142 $this->linkDb[$link['id']] = $link;
143 $this->linkDb->save($this->conf->get('resource.page_cache'));
144 $this->history->addLink($link);
145 $out = ApiUtils::formatLink($link, index_url($this->ci['environment']));
146 $redirect = $this->ci->router->relativePathFor('getLink', ['id' => $link['id']]);
147 return $response->withAddedHeader('Location', $redirect)
148 ->withJson($out, 201, $this->jsonStyle);
149 }
150
151 /**
152 * Updates an existing link from posted request body.
153 *
154 * @param Request $request Slim request.
155 * @param Response $response Slim response.
156 * @param array $args Path parameters. including the ID.
157 *
158 * @return Response response.
159 *
160 * @throws ApiLinkNotFoundException generating a 404 error.
161 */
162 public function putLink($request, $response, $args)
163 {
164 if (! isset($this->linkDb[$args['id']])) {
165 throw new ApiLinkNotFoundException();
166 }
167
168 $index = index_url($this->ci['environment']);
169 $data = $request->getParsedBody();
170
171 $requestLink = ApiUtils::buildLinkFromRequest($data, $this->conf->get('privacy.default_private_links'));
172 // duplicate URL on a different link, return 409 Conflict
173 if (! empty($requestLink['url'])
174 && ! empty($dup = $this->linkDb->getLinkFromUrl($requestLink['url']))
175 && $dup['id'] != $args['id']
176 ) {
177 return $response->withJson(
178 ApiUtils::formatLink($dup, $index),
179 409,
180 $this->jsonStyle
181 );
182 }
183
184 $responseLink = $this->linkDb[$args['id']];
185 $responseLink = ApiUtils::updateLink($responseLink, $requestLink);
186 $this->linkDb[$responseLink['id']] = $responseLink;
187 $this->linkDb->save($this->conf->get('resource.page_cache'));
188 $this->history->updateLink($responseLink);
189
190 $out = ApiUtils::formatLink($responseLink, $index);
191 return $response->withJson($out, 200, $this->jsonStyle);
192 }
193
194 /**
195 * Delete an existing link by its ID.
196 *
197 * @param Request $request Slim request.
198 * @param Response $response Slim response.
199 * @param array $args Path parameters. including the ID.
200 *
201 * @return Response response.
202 *
203 * @throws ApiLinkNotFoundException generating a 404 error.
204 */
205 public function deleteLink($request, $response, $args)
206 {
207 if (! isset($this->linkDb[$args['id']])) {
208 throw new ApiLinkNotFoundException();
209 }
210 $link = $this->linkDb[$args['id']];
211 unset($this->linkDb[(int) $args['id']]);
212 $this->linkDb->save($this->conf->get('resource.page_cache'));
213 $this->history->deleteLink($link);
214
215 return $response->withStatus(204);
216 }
107} 217}