aboutsummaryrefslogtreecommitdiffhomepage
path: root/application/api/controllers/Tags.php
blob: 5a23f6db7d314ff3e7cd3a376392575616426287 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
<?php

namespace Shaarli\Api\Controllers;

use Shaarli\Api\ApiUtils;
use Shaarli\Api\Exceptions\ApiBadParametersException;
use Shaarli\Api\Exceptions\ApiTagNotFoundException;
use Shaarli\Bookmark\BookmarkFilter;
use Slim\Http\Request;
use Slim\Http\Response;

/**
 * Class Tags
 *
 * REST API Controller: all services related to tags collection.
 *
 * @package Api\Controllers
 */
class Tags extends ApiController
{
    /**
     * @var int Number of bookmarks returned if no limit is provided.
     */
    public static $DEFAULT_LIMIT = 'all';

    /**
     * Retrieve a list of tags, allowing different filters.
     *
     * @param Request  $request  Slim request.
     * @param Response $response Slim response.
     *
     * @return Response response.
     *
     * @throws ApiBadParametersException Invalid parameters.
     */
    public function getTags($request, $response)
    {
        $visibility = $request->getParam('visibility');
        $tags = $this->bookmarkService->bookmarksCountPerTag([], $visibility);

        // Return tags from the {offset}th tag, starting from 0.
        $offset = $request->getParam('offset');
        if (! empty($offset) && ! ctype_digit($offset)) {
            throw new ApiBadParametersException('Invalid offset');
        }
        $offset = ! empty($offset) ? intval($offset) : 0;
        if ($offset > count($tags)) {
            return $response->withJson([], 200, $this->jsonStyle);
        }

        // limit parameter is either a number of bookmarks or 'all' for everything.
        $limit = $request->getParam('limit');
        if (empty($limit)) {
            $limit = self::$DEFAULT_LIMIT;
        }
        if (ctype_digit($limit)) {
            $limit = intval($limit);
        } elseif ($limit === 'all') {
            $limit = count($tags);
        } else {
            throw new ApiBadParametersException('Invalid limit');
        }

        $out = [];
        $index = 0;
        foreach ($tags as $tag => $occurrences) {
            if (count($out) >= $limit) {
                break;
            }
            if ($index++ >= $offset) {
                $out[] = ApiUtils::formatTag($tag, $occurrences);
            }
        }

        return $response->withJson($out, 200, $this->jsonStyle);
    }

    /**
     * Return a single formatted tag by its name.
     *
     * @param Request  $request  Slim request.
     * @param Response $response Slim response.
     * @param array    $args     Path parameters. including the tag name.
     *
     * @return Response containing the link array.
     *
     * @throws ApiTagNotFoundException generating a 404 error.
     */
    public function getTag($request, $response, $args)
    {
        $tags = $this->bookmarkService->bookmarksCountPerTag();
        if (!isset($tags[$args['tagName']])) {
            throw new ApiTagNotFoundException();
        }
        $out = ApiUtils::formatTag($args['tagName'], $tags[$args['tagName']]);

        return $response->withJson($out, 200, $this->jsonStyle);
    }

    /**
     * Rename a tag from the given name.
     * If the new name provided matches an existing tag, they will be merged.
     *
     * @param Request  $request  Slim request.
     * @param Response $response Slim response.
     * @param array    $args     Path parameters. including the tag name.
     *
     * @return Response response.
     *
     * @throws ApiTagNotFoundException generating a 404 error.
     * @throws ApiBadParametersException new tag name not provided
     */
    public function putTag($request, $response, $args)
    {
        $tags = $this->bookmarkService->bookmarksCountPerTag();
        if (! isset($tags[$args['tagName']])) {
            throw new ApiTagNotFoundException();
        }

        $data = $request->getParsedBody();
        if (empty($data['name'])) {
            throw new ApiBadParametersException('New tag name is required in the request body');
        }

        $searchResult = $this->bookmarkService->search(
            ['searchtags' => $args['tagName']],
            BookmarkFilter::$ALL,
            true
        );
        foreach ($searchResult->getBookmarks() as $bookmark) {
            $bookmark->renameTag($args['tagName'], $data['name']);
            $this->bookmarkService->set($bookmark, false);
            $this->history->updateLink($bookmark);
        }
        $this->bookmarkService->save();

        $tags = $this->bookmarkService->bookmarksCountPerTag();
        $out = ApiUtils::formatTag($data['name'], $tags[$data['name']]);
        return $response->withJson($out, 200, $this->jsonStyle);
    }

    /**
     * Delete an existing tag by its name.
     *
     * @param Request  $request  Slim request.
     * @param Response $response Slim response.
     * @param array    $args     Path parameters. including the tag name.
     *
     * @return Response response.
     *
     * @throws ApiTagNotFoundException generating a 404 error.
     */
    public function deleteTag($request, $response, $args)
    {
        $tags = $this->bookmarkService->bookmarksCountPerTag();
        if (! isset($tags[$args['tagName']])) {
            throw new ApiTagNotFoundException();
        }

        $searchResult = $this->bookmarkService->search(
            ['searchtags' => $args['tagName']],
            BookmarkFilter::$ALL,
            true
        );
        foreach ($searchResult->getBookmarks() as $bookmark) {
            $bookmark->deleteTag($args['tagName']);
            $this->bookmarkService->set($bookmark, false);
            $this->history->updateLink($bookmark);
        }
        $this->bookmarkService->save();

        return $response->withStatus(204);
    }
}