aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorArthurHoaro <arthur@hoa.ro>2017-05-06 17:32:16 +0200
committerArthurHoaro <arthur@hoa.ro>2017-05-07 15:58:49 +0200
commit0843848c1d18e92504c43d181063a2012f8fd5b9 (patch)
treefaf798ea7d1e4a41edce202cebd0cd7d45e22300
parentcf9181dddf8b6113b1b017e4bcb21fac0a0b1c83 (diff)
downloadShaarli-0843848c1d18e92504c43d181063a2012f8fd5b9.tar.gz
Shaarli-0843848c1d18e92504c43d181063a2012f8fd5b9.tar.zst
Shaarli-0843848c1d18e92504c43d181063a2012f8fd5b9.zip
API: add DELETE endpoint
Based on #840 See http://shaarli.github.io/api-documentation/\#links-link-delete
-rw-r--r--application/api/controllers/Links.php23
-rw-r--r--composer.lock80
-rw-r--r--index.php1
-rw-r--r--tests/api/controllers/DeleteLinkTest.php104
4 files changed, 168 insertions, 40 deletions
diff --git a/application/api/controllers/Links.php b/application/api/controllers/Links.php
index 1c68b062..a40e974d 100644
--- a/application/api/controllers/Links.php
+++ b/application/api/controllers/Links.php
@@ -188,4 +188,27 @@ class Links extends ApiController
188 $out = ApiUtils::formatLink($responseLink, $index); 188 $out = ApiUtils::formatLink($responseLink, $index);
189 return $response->withJson($out, 200, $this->jsonStyle); 189 return $response->withJson($out, 200, $this->jsonStyle);
190 } 190 }
191
192 /**
193 * Delete an existing link by its ID.
194 *
195 * @param Request $request Slim request.
196 * @param Response $response Slim response.
197 * @param array $args Path parameters. including the ID.
198 *
199 * @return Response response.
200 *
201 * @throws ApiLinkNotFoundException generating a 404 error.
202 */
203 public function deleteLink($request, $response, $args)
204 {
205 if (! isset($this->linkDb[$args['id']])) {
206 throw new ApiLinkNotFoundException();
207 }
208
209 unset($this->linkDb[(int) $args['id']]);
210 $this->linkDb->save($this->conf->get('resource.page_cache'));
211
212 return $response->withStatus(204);
213 }
191} 214}
diff --git a/composer.lock b/composer.lock
index b285fcc9..0c1efa6b 100644
--- a/composer.lock
+++ b/composer.lock
@@ -1793,16 +1793,16 @@
1793 }, 1793 },
1794 { 1794 {
1795 "name": "squizlabs/php_codesniffer", 1795 "name": "squizlabs/php_codesniffer",
1796 "version": "2.8.1", 1796 "version": "2.9.0",
1797 "source": { 1797 "source": {
1798 "type": "git", 1798 "type": "git",
1799 "url": "https://github.com/squizlabs/PHP_CodeSniffer.git", 1799 "url": "https://github.com/squizlabs/PHP_CodeSniffer.git",
1800 "reference": "d7cf0d894e8aa4c73712ee4a331cc1eaa37cdc7d" 1800 "reference": "f7dfecbee89d68ab475a6c9e17d22bc9b69aed97"
1801 }, 1801 },
1802 "dist": { 1802 "dist": {
1803 "type": "zip", 1803 "type": "zip",
1804 "url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/d7cf0d894e8aa4c73712ee4a331cc1eaa37cdc7d", 1804 "url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/f7dfecbee89d68ab475a6c9e17d22bc9b69aed97",
1805 "reference": "d7cf0d894e8aa4c73712ee4a331cc1eaa37cdc7d", 1805 "reference": "f7dfecbee89d68ab475a6c9e17d22bc9b69aed97",
1806 "shasum": "" 1806 "shasum": ""
1807 }, 1807 },
1808 "require": { 1808 "require": {
@@ -1867,20 +1867,20 @@
1867 "phpcs", 1867 "phpcs",
1868 "standards" 1868 "standards"
1869 ], 1869 ],
1870 "time": "2017-03-01T22:17:45+00:00" 1870 "time": "2017-05-03T23:30:39+00:00"
1871 }, 1871 },
1872 { 1872 {
1873 "name": "symfony/config", 1873 "name": "symfony/config",
1874 "version": "v3.2.6", 1874 "version": "v3.2.8",
1875 "source": { 1875 "source": {
1876 "type": "git", 1876 "type": "git",
1877 "url": "https://github.com/symfony/config.git", 1877 "url": "https://github.com/symfony/config.git",
1878 "reference": "741d6d4cd1414d67d48eb71aba6072b46ba740c2" 1878 "reference": "e5533fcc0b3dd377626153b2852707878f363728"
1879 }, 1879 },
1880 "dist": { 1880 "dist": {
1881 "type": "zip", 1881 "type": "zip",
1882 "url": "https://api.github.com/repos/symfony/config/zipball/741d6d4cd1414d67d48eb71aba6072b46ba740c2", 1882 "url": "https://api.github.com/repos/symfony/config/zipball/e5533fcc0b3dd377626153b2852707878f363728",
1883 "reference": "741d6d4cd1414d67d48eb71aba6072b46ba740c2", 1883 "reference": "e5533fcc0b3dd377626153b2852707878f363728",
1884 "shasum": "" 1884 "shasum": ""
1885 }, 1885 },
1886 "require": { 1886 "require": {
@@ -1923,20 +1923,20 @@
1923 ], 1923 ],
1924 "description": "Symfony Config Component", 1924 "description": "Symfony Config Component",
1925 "homepage": "https://symfony.com", 1925 "homepage": "https://symfony.com",
1926 "time": "2017-03-01T18:18:25+00:00" 1926 "time": "2017-04-12T14:13:17+00:00"
1927 }, 1927 },
1928 { 1928 {
1929 "name": "symfony/console", 1929 "name": "symfony/console",
1930 "version": "v2.8.18", 1930 "version": "v2.8.20",
1931 "source": { 1931 "source": {
1932 "type": "git", 1932 "type": "git",
1933 "url": "https://github.com/symfony/console.git", 1933 "url": "https://github.com/symfony/console.git",
1934 "reference": "81508e6fac4476771275a3f4f53c3fee9b956bfa" 1934 "reference": "2cfcbced8e39e2313ed4da8896fc8c59a56c0d7e"
1935 }, 1935 },
1936 "dist": { 1936 "dist": {
1937 "type": "zip", 1937 "type": "zip",
1938 "url": "https://api.github.com/repos/symfony/console/zipball/81508e6fac4476771275a3f4f53c3fee9b956bfa", 1938 "url": "https://api.github.com/repos/symfony/console/zipball/2cfcbced8e39e2313ed4da8896fc8c59a56c0d7e",
1939 "reference": "81508e6fac4476771275a3f4f53c3fee9b956bfa", 1939 "reference": "2cfcbced8e39e2313ed4da8896fc8c59a56c0d7e",
1940 "shasum": "" 1940 "shasum": ""
1941 }, 1941 },
1942 "require": { 1942 "require": {
@@ -1984,7 +1984,7 @@
1984 ], 1984 ],
1985 "description": "Symfony Console Component", 1985 "description": "Symfony Console Component",
1986 "homepage": "https://symfony.com", 1986 "homepage": "https://symfony.com",
1987 "time": "2017-03-04T11:00:12+00:00" 1987 "time": "2017-04-26T01:38:53+00:00"
1988 }, 1988 },
1989 { 1989 {
1990 "name": "symfony/debug", 1990 "name": "symfony/debug",
@@ -2045,16 +2045,16 @@
2045 }, 2045 },
2046 { 2046 {
2047 "name": "symfony/dependency-injection", 2047 "name": "symfony/dependency-injection",
2048 "version": "v3.2.6", 2048 "version": "v3.2.8",
2049 "source": { 2049 "source": {
2050 "type": "git", 2050 "type": "git",
2051 "url": "https://github.com/symfony/dependency-injection.git", 2051 "url": "https://github.com/symfony/dependency-injection.git",
2052 "reference": "74e0935e414ad33d5e82074212c0eedb4681a691" 2052 "reference": "5e00857475b6d1fa31ff4c76f1fddf1cfa9e8d59"
2053 }, 2053 },
2054 "dist": { 2054 "dist": {
2055 "type": "zip", 2055 "type": "zip",
2056 "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/74e0935e414ad33d5e82074212c0eedb4681a691", 2056 "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/5e00857475b6d1fa31ff4c76f1fddf1cfa9e8d59",
2057 "reference": "74e0935e414ad33d5e82074212c0eedb4681a691", 2057 "reference": "5e00857475b6d1fa31ff4c76f1fddf1cfa9e8d59",
2058 "shasum": "" 2058 "shasum": ""
2059 }, 2059 },
2060 "require": { 2060 "require": {
@@ -2104,20 +2104,20 @@
2104 ], 2104 ],
2105 "description": "Symfony DependencyInjection Component", 2105 "description": "Symfony DependencyInjection Component",
2106 "homepage": "https://symfony.com", 2106 "homepage": "https://symfony.com",
2107 "time": "2017-03-05T00:06:55+00:00" 2107 "time": "2017-04-26T01:39:17+00:00"
2108 }, 2108 },
2109 { 2109 {
2110 "name": "symfony/filesystem", 2110 "name": "symfony/filesystem",
2111 "version": "v3.2.6", 2111 "version": "v3.2.8",
2112 "source": { 2112 "source": {
2113 "type": "git", 2113 "type": "git",
2114 "url": "https://github.com/symfony/filesystem.git", 2114 "url": "https://github.com/symfony/filesystem.git",
2115 "reference": "bc0f17bed914df2cceb989972c3b996043c4da4a" 2115 "reference": "040651db13cf061827a460cc10f6e36a445c45b4"
2116 }, 2116 },
2117 "dist": { 2117 "dist": {
2118 "type": "zip", 2118 "type": "zip",
2119 "url": "https://api.github.com/repos/symfony/filesystem/zipball/bc0f17bed914df2cceb989972c3b996043c4da4a", 2119 "url": "https://api.github.com/repos/symfony/filesystem/zipball/040651db13cf061827a460cc10f6e36a445c45b4",
2120 "reference": "bc0f17bed914df2cceb989972c3b996043c4da4a", 2120 "reference": "040651db13cf061827a460cc10f6e36a445c45b4",
2121 "shasum": "" 2121 "shasum": ""
2122 }, 2122 },
2123 "require": { 2123 "require": {
@@ -2153,20 +2153,20 @@
2153 ], 2153 ],
2154 "description": "Symfony Filesystem Component", 2154 "description": "Symfony Filesystem Component",
2155 "homepage": "https://symfony.com", 2155 "homepage": "https://symfony.com",
2156 "time": "2017-03-06T19:30:27+00:00" 2156 "time": "2017-04-12T14:13:17+00:00"
2157 }, 2157 },
2158 { 2158 {
2159 "name": "symfony/finder", 2159 "name": "symfony/finder",
2160 "version": "v3.2.6", 2160 "version": "v3.2.8",
2161 "source": { 2161 "source": {
2162 "type": "git", 2162 "type": "git",
2163 "url": "https://github.com/symfony/finder.git", 2163 "url": "https://github.com/symfony/finder.git",
2164 "reference": "92d7476d2df60cd851a3e13e078664b1deb8ce10" 2164 "reference": "9cf076f8f492f4b1ffac40aae9c2d287b4ca6930"
2165 }, 2165 },
2166 "dist": { 2166 "dist": {
2167 "type": "zip", 2167 "type": "zip",
2168 "url": "https://api.github.com/repos/symfony/finder/zipball/92d7476d2df60cd851a3e13e078664b1deb8ce10", 2168 "url": "https://api.github.com/repos/symfony/finder/zipball/9cf076f8f492f4b1ffac40aae9c2d287b4ca6930",
2169 "reference": "92d7476d2df60cd851a3e13e078664b1deb8ce10", 2169 "reference": "9cf076f8f492f4b1ffac40aae9c2d287b4ca6930",
2170 "shasum": "" 2170 "shasum": ""
2171 }, 2171 },
2172 "require": { 2172 "require": {
@@ -2202,7 +2202,7 @@
2202 ], 2202 ],
2203 "description": "Symfony Finder Component", 2203 "description": "Symfony Finder Component",
2204 "homepage": "https://symfony.com", 2204 "homepage": "https://symfony.com",
2205 "time": "2017-02-21T09:12:04+00:00" 2205 "time": "2017-04-12T14:13:17+00:00"
2206 }, 2206 },
2207 { 2207 {
2208 "name": "symfony/polyfill-mbstring", 2208 "name": "symfony/polyfill-mbstring",
@@ -2265,16 +2265,16 @@
2265 }, 2265 },
2266 { 2266 {
2267 "name": "symfony/yaml", 2267 "name": "symfony/yaml",
2268 "version": "v3.2.6", 2268 "version": "v3.2.8",
2269 "source": { 2269 "source": {
2270 "type": "git", 2270 "type": "git",
2271 "url": "https://github.com/symfony/yaml.git", 2271 "url": "https://github.com/symfony/yaml.git",
2272 "reference": "093e416ad096355149e265ea2e4cc1f9ee40ab1a" 2272 "reference": "acec26fcf7f3031e094e910b94b002fa53d4e4d6"
2273 }, 2273 },
2274 "dist": { 2274 "dist": {
2275 "type": "zip", 2275 "type": "zip",
2276 "url": "https://api.github.com/repos/symfony/yaml/zipball/093e416ad096355149e265ea2e4cc1f9ee40ab1a", 2276 "url": "https://api.github.com/repos/symfony/yaml/zipball/acec26fcf7f3031e094e910b94b002fa53d4e4d6",
2277 "reference": "093e416ad096355149e265ea2e4cc1f9ee40ab1a", 2277 "reference": "acec26fcf7f3031e094e910b94b002fa53d4e4d6",
2278 "shasum": "" 2278 "shasum": ""
2279 }, 2279 },
2280 "require": { 2280 "require": {
@@ -2316,20 +2316,20 @@
2316 ], 2316 ],
2317 "description": "Symfony Yaml Component", 2317 "description": "Symfony Yaml Component",
2318 "homepage": "https://symfony.com", 2318 "homepage": "https://symfony.com",
2319 "time": "2017-03-07T16:47:02+00:00" 2319 "time": "2017-05-01T14:55:58+00:00"
2320 }, 2320 },
2321 { 2321 {
2322 "name": "theseer/fdomdocument", 2322 "name": "theseer/fdomdocument",
2323 "version": "1.6.1", 2323 "version": "1.6.5",
2324 "source": { 2324 "source": {
2325 "type": "git", 2325 "type": "git",
2326 "url": "https://github.com/theseer/fDOMDocument.git", 2326 "url": "https://github.com/theseer/fDOMDocument.git",
2327 "reference": "d9ad139d6c2e8edf5e313ffbe37ff13344cf0684" 2327 "reference": "8dcfd392135a5bd938c3c83ea71419501ad9855d"
2328 }, 2328 },
2329 "dist": { 2329 "dist": {
2330 "type": "zip", 2330 "type": "zip",
2331 "url": "https://api.github.com/repos/theseer/fDOMDocument/zipball/d9ad139d6c2e8edf5e313ffbe37ff13344cf0684", 2331 "url": "https://api.github.com/repos/theseer/fDOMDocument/zipball/8dcfd392135a5bd938c3c83ea71419501ad9855d",
2332 "reference": "d9ad139d6c2e8edf5e313ffbe37ff13344cf0684", 2332 "reference": "8dcfd392135a5bd938c3c83ea71419501ad9855d",
2333 "shasum": "" 2333 "shasum": ""
2334 }, 2334 },
2335 "require": { 2335 "require": {
@@ -2356,7 +2356,7 @@
2356 ], 2356 ],
2357 "description": "The classes contained within this repository extend the standard DOM to use exceptions at all occasions of errors instead of PHP warnings or notices. They also add various custom methods and shortcuts for convenience and to simplify the usage of DOM.", 2357 "description": "The classes contained within this repository extend the standard DOM to use exceptions at all occasions of errors instead of PHP warnings or notices. They also add various custom methods and shortcuts for convenience and to simplify the usage of DOM.",
2358 "homepage": "https://github.com/theseer/fDOMDocument", 2358 "homepage": "https://github.com/theseer/fDOMDocument",
2359 "time": "2015-05-27T22:58:02+00:00" 2359 "time": "2017-04-21T14:50:31+00:00"
2360 }, 2360 },
2361 { 2361 {
2362 "name": "webmozart/assert", 2362 "name": "webmozart/assert",
diff --git a/index.php b/index.php
index d6642b68..6eaa56c2 100644
--- a/index.php
+++ b/index.php
@@ -2247,6 +2247,7 @@ $app->group('/api/v1', function() {
2247 $this->get('/links/{id:[\d]+}', '\Shaarli\Api\Controllers\Links:getLink')->setName('getLink'); 2247 $this->get('/links/{id:[\d]+}', '\Shaarli\Api\Controllers\Links:getLink')->setName('getLink');
2248 $this->post('/links', '\Shaarli\Api\Controllers\Links:postLink')->setName('postLink'); 2248 $this->post('/links', '\Shaarli\Api\Controllers\Links:postLink')->setName('postLink');
2249 $this->put('/links/{id:[\d]+}', '\Shaarli\Api\Controllers\Links:putLink')->setName('putLink'); 2249 $this->put('/links/{id:[\d]+}', '\Shaarli\Api\Controllers\Links:putLink')->setName('putLink');
2250 $this->delete('/links/{id:[\d]+}', '\Shaarli\Api\Controllers\Links:deleteLink')->setName('deleteLink');
2250})->add('\Shaarli\Api\ApiMiddleware'); 2251})->add('\Shaarli\Api\ApiMiddleware');
2251 2252
2252$response = $app->run(true); 2253$response = $app->run(true);
diff --git a/tests/api/controllers/DeleteLinkTest.php b/tests/api/controllers/DeleteLinkTest.php
new file mode 100644
index 00000000..6894e8a2
--- /dev/null
+++ b/tests/api/controllers/DeleteLinkTest.php
@@ -0,0 +1,104 @@
1<?php
2
3
4namespace Shaarli\Api\Controllers;
5
6use Shaarli\Config\ConfigManager;
7use Slim\Container;
8use Slim\Http\Environment;
9use Slim\Http\Request;
10use Slim\Http\Response;
11
12class DeleteLinkTest extends \PHPUnit_Framework_TestCase
13{
14 /**
15 * @var string datastore to test write operations
16 */
17 protected static $testDatastore = 'sandbox/datastore.php';
18
19 /**
20 * @var ConfigManager instance
21 */
22 protected $conf;
23
24 /**
25 * @var \ReferenceLinkDB instance.
26 */
27 protected $refDB = null;
28
29 /**
30 * @var \LinkDB instance.
31 */
32 protected $linkDB;
33
34 /**
35 * @var Container instance.
36 */
37 protected $container;
38
39 /**
40 * @var Links controller instance.
41 */
42 protected $controller;
43
44 /**
45 * Before each test, instantiate a new Api with its config, plugins and links.
46 */
47 public function setUp()
48 {
49 $this->conf = new ConfigManager('tests/utils/config/configJson');
50 $this->refDB = new \ReferenceLinkDB();
51 $this->refDB->write(self::$testDatastore);
52 $this->linkDB = new \LinkDB(self::$testDatastore, true, false);
53 $this->container = new Container();
54 $this->container['conf'] = $this->conf;
55 $this->container['db'] = $this->linkDB;
56
57 $this->controller = new Links($this->container);
58 }
59
60 /**
61 * After each test, remove the test datastore.
62 */
63 public function tearDown()
64 {
65 @unlink(self::$testDatastore);
66 }
67
68 /**
69 * Test DELETE link endpoint: the link should be removed.
70 */
71 public function testDeleteLinkValid()
72 {
73 $id = '41';
74 $this->assertTrue(isset($this->linkDB[$id]));
75 $env = Environment::mock([
76 'REQUEST_METHOD' => 'DELETE',
77 ]);
78 $request = Request::createFromEnvironment($env);
79
80 $response = $this->controller->deleteLink($request, new Response(), ['id' => $id]);
81 $this->assertEquals(204, $response->getStatusCode());
82 $this->assertEmpty((string) $response->getBody());
83
84 $this->linkDB = new \LinkDB(self::$testDatastore, true, false);
85 $this->assertFalse(isset($this->linkDB[$id]));
86 }
87
88 /**
89 * Test DELETE link endpoint: reach not existing ID.
90 *
91 * @expectedException Shaarli\Api\Exceptions\ApiLinkNotFoundException
92 */
93 public function testDeleteLink404()
94 {
95 $id = -1;
96 $this->assertFalse(isset($this->linkDB[$id]));
97 $env = Environment::mock([
98 'REQUEST_METHOD' => 'DELETE',
99 ]);
100 $request = Request::createFromEnvironment($env);
101
102 $this->controller->deleteLink($request, new Response(), ['id' => $id]);
103 }
104}