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
* If no URL is provided, it will generate a local note URL.
* If no title is provided, it will use the URL as title.
*
- * @param array|null $input Request Link.
- * @param bool $defaultPrivate Setting defined if a bookmark is private by default.
+ * @param array|null $input Request Link.
+ * @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.
*/
- public static function buildBookmarkFromRequest(?array $input, bool $defaultPrivate): Bookmark
- {
+ public static function buildBookmarkFromRequest(
+ ?array $input,
+ bool $defaultPrivate,
+ string $tagsSeparator
+ ): Bookmark {
$bookmark = new Bookmark();
$url = ! empty($input['url']) ? cleanup_url($input['url']) : '';
if (isset($input['private'])) {
$bookmark->setTitle(! empty($input['title']) ? $input['title'] : '');
$bookmark->setUrl($url);
$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->setPrivate($private);
public function postLink($request, $response)
{
$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
if (
! empty($bookmark->getUrl())
$index = index_url($this->ci['environment']);
$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
if (
! empty($requestBookmark->getUrl())
\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']);
+ }
}
$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']);
+ }
}