diff options
author | ArthurHoaro <arthur@hoa.ro> | 2017-05-07 16:02:14 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-05-07 16:02:14 +0200 |
commit | b8fcb7d4403a344158ab5d2c8979bdd002e6001d (patch) | |
tree | 2ac6304cfdef1322c19bd47ba972e8894d98ab68 | |
parent | 77de24876ff542e3770aa2845e993c58f87e37df (diff) | |
parent | 0843848c1d18e92504c43d181063a2012f8fd5b9 (diff) | |
download | Shaarli-b8fcb7d4403a344158ab5d2c8979bdd002e6001d.tar.gz Shaarli-b8fcb7d4403a344158ab5d2c8979bdd002e6001d.tar.zst Shaarli-b8fcb7d4403a344158ab5d2c8979bdd002e6001d.zip |
Merge pull request #856 from ArthurHoaro/api/delete-link
API: add DELETE endpoint
-rw-r--r-- | application/api/controllers/Links.php | 23 | ||||
-rw-r--r-- | composer.lock | 80 | ||||
-rw-r--r-- | index.php | 1 | ||||
-rw-r--r-- | tests/api/controllers/DeleteLinkTest.php | 104 |
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", |
@@ -2252,6 +2252,7 @@ $app->group('/api/v1', function() { | |||
2252 | $this->get('/links/{id:[\d]+}', '\Shaarli\Api\Controllers\Links:getLink')->setName('getLink'); | 2252 | $this->get('/links/{id:[\d]+}', '\Shaarli\Api\Controllers\Links:getLink')->setName('getLink'); |
2253 | $this->post('/links', '\Shaarli\Api\Controllers\Links:postLink')->setName('postLink'); | 2253 | $this->post('/links', '\Shaarli\Api\Controllers\Links:postLink')->setName('postLink'); |
2254 | $this->put('/links/{id:[\d]+}', '\Shaarli\Api\Controllers\Links:putLink')->setName('putLink'); | 2254 | $this->put('/links/{id:[\d]+}', '\Shaarli\Api\Controllers\Links:putLink')->setName('putLink'); |
2255 | $this->delete('/links/{id:[\d]+}', '\Shaarli\Api\Controllers\Links:deleteLink')->setName('deleteLink'); | ||
2255 | })->add('\Shaarli\Api\ApiMiddleware'); | 2256 | })->add('\Shaarli\Api\ApiMiddleware'); |
2256 | 2257 | ||
2257 | $response = $app->run(true); | 2258 | $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 | |||
4 | namespace Shaarli\Api\Controllers; | ||
5 | |||
6 | use Shaarli\Config\ConfigManager; | ||
7 | use Slim\Container; | ||
8 | use Slim\Http\Environment; | ||
9 | use Slim\Http\Request; | ||
10 | use Slim\Http\Response; | ||
11 | |||
12 | class 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 | } | ||