API: POST/PUT Link - properly parse tags string
Even though the documentation specify that tags should be passed as an array, tags string is actually allowed. So this adds a proper parsing with configured separator. Related to #1651
This commit is contained in:
parent
fe58bdcd9e
commit
0640c1a6db
4 changed files with 123 additions and 6 deletions
|
@ -93,11 +93,15 @@ public static function formatLink($bookmark, $indexUrl)
|
||||||
*
|
*
|
||||||
* @param array|null $input Request Link.
|
* @param array|null $input Request Link.
|
||||||
* @param bool $defaultPrivate Setting defined if a bookmark is private by default.
|
* @param bool $defaultPrivate Setting defined if a bookmark is private by default.
|
||||||
|
* @param string $tagsSeparator Tags separator loaded from the config file.
|
||||||
*
|
*
|
||||||
* @return Bookmark instance.
|
* @return Bookmark instance.
|
||||||
*/
|
*/
|
||||||
public static function buildBookmarkFromRequest(?array $input, bool $defaultPrivate): Bookmark
|
public static function buildBookmarkFromRequest(
|
||||||
{
|
?array $input,
|
||||||
|
bool $defaultPrivate,
|
||||||
|
string $tagsSeparator
|
||||||
|
): Bookmark {
|
||||||
$bookmark = new Bookmark();
|
$bookmark = new Bookmark();
|
||||||
$url = ! empty($input['url']) ? cleanup_url($input['url']) : '';
|
$url = ! empty($input['url']) ? cleanup_url($input['url']) : '';
|
||||||
if (isset($input['private'])) {
|
if (isset($input['private'])) {
|
||||||
|
@ -109,6 +113,15 @@ public static function buildBookmarkFromRequest(?array $input, bool $defaultPriv
|
||||||
$bookmark->setTitle(! empty($input['title']) ? $input['title'] : '');
|
$bookmark->setTitle(! empty($input['title']) ? $input['title'] : '');
|
||||||
$bookmark->setUrl($url);
|
$bookmark->setUrl($url);
|
||||||
$bookmark->setDescription(! empty($input['description']) ? $input['description'] : '');
|
$bookmark->setDescription(! empty($input['description']) ? $input['description'] : '');
|
||||||
|
|
||||||
|
// Be permissive with provided tags format
|
||||||
|
if (is_string($input['tags'] ?? null)) {
|
||||||
|
$input['tags'] = tags_str2array($input['tags'], $tagsSeparator);
|
||||||
|
}
|
||||||
|
if (is_array($input['tags'] ?? null) && count($input['tags']) === 1 && is_string($input['tags'][0])) {
|
||||||
|
$input['tags'] = tags_str2array($input['tags'][0], $tagsSeparator);
|
||||||
|
}
|
||||||
|
|
||||||
$bookmark->setTags(! empty($input['tags']) ? $input['tags'] : []);
|
$bookmark->setTags(! empty($input['tags']) ? $input['tags'] : []);
|
||||||
$bookmark->setPrivate($private);
|
$bookmark->setPrivate($private);
|
||||||
|
|
||||||
|
|
|
@ -117,7 +117,11 @@ public function getLink($request, $response, $args)
|
||||||
public function postLink($request, $response)
|
public function postLink($request, $response)
|
||||||
{
|
{
|
||||||
$data = (array) ($request->getParsedBody() ?? []);
|
$data = (array) ($request->getParsedBody() ?? []);
|
||||||
$bookmark = ApiUtils::buildBookmarkFromRequest($data, $this->conf->get('privacy.default_private_links'));
|
$bookmark = ApiUtils::buildBookmarkFromRequest(
|
||||||
|
$data,
|
||||||
|
$this->conf->get('privacy.default_private_links'),
|
||||||
|
$this->conf->get('general.tags_separator', ' ')
|
||||||
|
);
|
||||||
// duplicate by URL, return 409 Conflict
|
// duplicate by URL, return 409 Conflict
|
||||||
if (
|
if (
|
||||||
! empty($bookmark->getUrl())
|
! empty($bookmark->getUrl())
|
||||||
|
@ -158,7 +162,11 @@ public function putLink($request, $response, $args)
|
||||||
$index = index_url($this->ci['environment']);
|
$index = index_url($this->ci['environment']);
|
||||||
$data = $request->getParsedBody();
|
$data = $request->getParsedBody();
|
||||||
|
|
||||||
$requestBookmark = ApiUtils::buildBookmarkFromRequest($data, $this->conf->get('privacy.default_private_links'));
|
$requestBookmark = ApiUtils::buildBookmarkFromRequest(
|
||||||
|
$data,
|
||||||
|
$this->conf->get('privacy.default_private_links'),
|
||||||
|
$this->conf->get('general.tags_separator', ' ')
|
||||||
|
);
|
||||||
// duplicate URL on a different link, return 409 Conflict
|
// duplicate URL on a different link, return 409 Conflict
|
||||||
if (
|
if (
|
||||||
! empty($requestBookmark->getUrl())
|
! empty($requestBookmark->getUrl())
|
||||||
|
|
|
@ -229,4 +229,52 @@ public function testPostLinkDuplicate()
|
||||||
\DateTime::createFromFormat(\DateTime::ATOM, $data['updated'])
|
\DateTime::createFromFormat(\DateTime::ATOM, $data['updated'])
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test link creation with a tag string provided
|
||||||
|
*/
|
||||||
|
public function testPostLinkWithTagString(): void
|
||||||
|
{
|
||||||
|
$link = [
|
||||||
|
'tags' => 'one two',
|
||||||
|
];
|
||||||
|
$env = Environment::mock([
|
||||||
|
'REQUEST_METHOD' => 'POST',
|
||||||
|
'CONTENT_TYPE' => 'application/json'
|
||||||
|
]);
|
||||||
|
|
||||||
|
$request = Request::createFromEnvironment($env);
|
||||||
|
$request = $request->withParsedBody($link);
|
||||||
|
$response = $this->controller->postLink($request, new Response());
|
||||||
|
|
||||||
|
$this->assertEquals(201, $response->getStatusCode());
|
||||||
|
$this->assertEquals('/api/v1/bookmarks/1', $response->getHeader('Location')[0]);
|
||||||
|
$data = json_decode((string) $response->getBody(), true);
|
||||||
|
$this->assertEquals(self::NB_FIELDS_LINK, count($data));
|
||||||
|
$this->assertEquals(['one', 'two'], $data['tags']);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test link creation with a tag string provided
|
||||||
|
*/
|
||||||
|
public function testPostLinkWithTagString2(): void
|
||||||
|
{
|
||||||
|
$link = [
|
||||||
|
'tags' => ['one two'],
|
||||||
|
];
|
||||||
|
$env = Environment::mock([
|
||||||
|
'REQUEST_METHOD' => 'POST',
|
||||||
|
'CONTENT_TYPE' => 'application/json'
|
||||||
|
]);
|
||||||
|
|
||||||
|
$request = Request::createFromEnvironment($env);
|
||||||
|
$request = $request->withParsedBody($link);
|
||||||
|
$response = $this->controller->postLink($request, new Response());
|
||||||
|
|
||||||
|
$this->assertEquals(201, $response->getStatusCode());
|
||||||
|
$this->assertEquals('/api/v1/bookmarks/1', $response->getHeader('Location')[0]);
|
||||||
|
$data = json_decode((string) $response->getBody(), true);
|
||||||
|
$this->assertEquals(self::NB_FIELDS_LINK, count($data));
|
||||||
|
$this->assertEquals(['one', 'two'], $data['tags']);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -233,4 +233,52 @@ public function testGetLink404()
|
||||||
|
|
||||||
$this->controller->putLink($request, new Response(), ['id' => -1]);
|
$this->controller->putLink($request, new Response(), ['id' => -1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test link creation with a tag string provided
|
||||||
|
*/
|
||||||
|
public function testPutLinkWithTagString(): void
|
||||||
|
{
|
||||||
|
$link = [
|
||||||
|
'tags' => 'one two',
|
||||||
|
];
|
||||||
|
$id = '41';
|
||||||
|
$env = Environment::mock([
|
||||||
|
'REQUEST_METHOD' => 'PUT',
|
||||||
|
'CONTENT_TYPE' => 'application/json'
|
||||||
|
]);
|
||||||
|
|
||||||
|
$request = Request::createFromEnvironment($env);
|
||||||
|
$request = $request->withParsedBody($link);
|
||||||
|
$response = $this->controller->putLink($request, new Response(), ['id' => $id]);
|
||||||
|
|
||||||
|
$this->assertEquals(200, $response->getStatusCode());
|
||||||
|
$data = json_decode((string) $response->getBody(), true);
|
||||||
|
$this->assertEquals(self::NB_FIELDS_LINK, count($data));
|
||||||
|
$this->assertEquals(['one', 'two'], $data['tags']);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test link creation with a tag string provided
|
||||||
|
*/
|
||||||
|
public function testPutLinkWithTagString2(): void
|
||||||
|
{
|
||||||
|
$link = [
|
||||||
|
'tags' => ['one two'],
|
||||||
|
];
|
||||||
|
$id = '41';
|
||||||
|
$env = Environment::mock([
|
||||||
|
'REQUEST_METHOD' => 'PUT',
|
||||||
|
'CONTENT_TYPE' => 'application/json'
|
||||||
|
]);
|
||||||
|
|
||||||
|
$request = Request::createFromEnvironment($env);
|
||||||
|
$request = $request->withParsedBody($link);
|
||||||
|
$response = $this->controller->putLink($request, new Response(), ['id' => $id]);
|
||||||
|
|
||||||
|
$this->assertEquals(200, $response->getStatusCode());
|
||||||
|
$data = json_decode((string) $response->getBody(), true);
|
||||||
|
$this->assertEquals(self::NB_FIELDS_LINK, count($data));
|
||||||
|
$this->assertEquals(['one', 'two'], $data['tags']);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue