Completed
Branch dev (bc6e47)
by Raffael
02:23
created

Notification::postSubscribe()   B

Complexity

Conditions 6
Paths 7

Size

Total Lines 33
Code Lines 20

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 33
rs 8.439
c 0
b 0
f 0
cc 6
eloc 20
nc 7
nop 3
1
<?php
2
3
declare(strict_types=1);
4
5
/**
6
 * Balloon
7
 *
8
 * @author      Raffael Sahli <[email protected]>
9
 * @copyright   Copryright (c) 2012-2017 gyselroth GmbH (https://gyselroth.com)
10
 * @license     GPL-3.0 https://opensource.org/licenses/GPL-3.0
11
 */
12
13
namespace Balloon\App\Notification\Api\v1;
14
15
use Balloon\Api\Controller;
16
use Balloon\App\Notification\Notifier;
17
use Balloon\Async\Mail;
18
use Balloon\Filesystem;
19
use Balloon\Filesystem\Acl\Exception\Forbidden as ForbiddenException;
20
use Balloon\Server;
21
use Balloon\Server\User;
22
use Micro\Http\Response;
23
use MongoDB\BSON\ObjectId;
24
use Psr\Log\LoggerInterface;
25
use TaskScheduler\Async;
26
use Zend\Mail\Message;
27
28
class Notification extends Controller
29
{
30
    /**
31
     * Notifier.
32
     *
33
     * @var Notifier
34
     */
35
    protected $notifier;
36
37
    /**
38
     * User.
39
     *
40
     * @var User
41
     */
42
    protected $user;
43
44
    /**
45
     * Filesystem.
46
     *
47
     * @var Filesystem
48
     */
49
    protected $fs;
50
51
    /**
52
     * Server.
53
     *
54
     * @var Server
55
     */
56
    protected $server;
57
58
    /**
59
     * Async.
60
     *
61
     * @var Async
62
     */
63
    protected $async;
64
65
    /**
66
     * Logger.
67
     *
68
     * @var LoggerInterface
69
     */
70
    protected $logger;
71
72
    /**
73
     * Constructor.
74
     *
75
     * @param Notifier        $notifier
76
     * @param Server          $server
77
     * @param Async           $async
78
     * @param LoggerInterface $logger
79
     */
80
    public function __construct(Notifier $notifier, Server $server, Async $async, LoggerInterface $logger)
81
    {
82
        $this->notifier = $notifier;
83
        $this->user = $server->getIdentity();
84
        $this->fs = $server->getFilesystem();
85
        $this->server = $server;
86
        $this->async = $async;
87
        $this->logger = $logger;
88
    }
89
90
    /**
91
     * @api {get} /api/v1/notification Get notifications
92
     * @apiVersion 1.0.0
93
     * @apiName get
94
     * @apiGroup App\Notification
95
     * @apiPermission none
96
     * @apiDescription Fetch my nofitifications
97
     *
98
     * @apiExample (cURL) exmaple:
99
     * curl -XGET "https://SERVER/api/v1/user/notification"
100
     *
101
     * @apiSuccessExample {string} Success-Response:
102
     * HTTP/1.1 200 OK
103
     * {
104
     *      "status": 200,
105
     *      "data": [{
106
     *          "message": "Hi there, this is a notification"
107
     *      }]
108
     * }
109
     */
110
    public function get(): Response
111
    {
112
        $body = [];
113
        foreach ($this->notifier->getNotifications($this->user) as $message) {
114
            $note = $message;
115
            $note['id'] = (string) $note['_id'];
116
            unset($note['_id'], $note['receiver']);
117
118
            $note['sender'] = $this->server->getUserById($note['sender'])->getAttribute([
119
                'id',
120
                'username',
121
            ]);
122
123
            $body[] = $note;
124
        }
125
126
        return (new Response())->setCode(200)->setBody($body);
127
    }
128
129
    /**
130
     * @api {delete} /api/v1/notification Delete notification
131
     * @apiVersion 1.0.0
132
     * @apiName get
133
     * @apiGroup App\Notification
134
     * @apiPermission none
135
     * @apiDescription Fetch my nofitifications
136
     *
137
     * @apiExample (cURL) exmaple:
138
     * curl -XGET "https://SERVER/api/v1/user/notification"
139
     *
140
     * @apiSuccessExample {string} Success-Response:
141
     * HTTP/1.1 204 No Content
142
     */
143
    public function delete(string $id): Response
144
    {
145
        $this->notifier->deleteNotification($this->user, new ObjectId($id));
146
147
        return (new Response())->setCode(204);
148
    }
149
150
    /**
151
     * @api {post} /api/v1/user/notification/broadcast Post a notification to all users (or to a bunch of users)
152
     * @apiVersion 1.0.0
153
     * @apiName get
154
     * @apiGroup App\Notification
155
     * @apiPermission admin
156
     * @apiDescription Send notification
157
     *
158
     * @apiExample (cURL) exmaple:
159
     * curl -XPOST "https://SERVER/api/v1/user/notification/broadcast"
160
     *
161
     * @apiSuccessExample {string} Success-Response:
162
     * HTTP/1.1 204 No Content
163
     */
164
    public function post(array $receiver, string $subject, string $body): Response
165
    {
166
        $users = $this->server->getUsersById($receiver);
0 ignored issues
show
Unused Code introduced by
$users is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
167
        $this->notifier->notify($receiver, $this->user, $subject, $body);
168
169
        return (new Response())->setCode(204);
170
    }
171
172
    /**
173
     * @api {post} /api/v1/notification/broadcast Post a notification to all users (or to a bunch of users)
174
     * @apiVersion 1.0.0
175
     * @apiName get
176
     * @apiGroup App\Notification
177
     * @apiPermission admin
178
     * @apiDescription Send notification
179
     *
180
     * @apiExample (cURL) exmaple:
181
     * curl -XPOST "https://SERVER/api/v1/user/notification/broadcast"
182
     *
183
     * @apiSuccessExample {string} Success-Response:
184
     * HTTP/1.1 204 No Content
185
     */
186
    public function postBroadcast(string $subject, string $body): Response
187
    {
188
        if (!$this->user->isAdmin()) {
189
            throw new ForbiddenException(
190
                'submitted parameters require to have admin privileges',
191
                    ForbiddenException::ADMIN_PRIV_REQUIRED
192
                );
193
        }
194
195
        $users = $this->server->getUsersByFilter([]);
0 ignored issues
show
Bug introduced by
The method getUsersByFilter() does not exist on Balloon\Server. Did you maybe mean getUsers()?

This check marks calls to methods that do not seem to exist on an object.

This is most likely the result of a method being renamed without all references to it being renamed likewise.

Loading history...
196
        $this->notifier->notify($users, $this->user, $subject, $body);
197
198
        return (new Response())->setCode(204);
199
    }
200
201
    /**
202
     * @api {post} /api/v1/notification/mail Send a normal mail message
203
     * @apiVersion 1.0.0
204
     * @apiName get
205
     * @apiGroup App\Notification
206
     * @apiPermission none
207
     * @apiDescription Send mail
208
     *
209
     * @apiExample (cURL) exmaple:
210
     * curl -XGET "https://SERVER/api/v1/user/notification"
211
     *
212
     * @apiSuccessExample {string} Success-Response:
213
     * HTTP/1.1 204 No Content
214
     */
215
    public function postMail(array $receiver, string $subject, string $body)
216
    {
217
        $mail = new Message();
218
        $mail->setBody($body);
219
        $mail->setFrom($this->user->getAttribute('username'), $this->user->getAttribute('mail'));
220
        $mail->setSubject($subject);
221
        $mail->setBcc($receiver);
222
        $this->async->addJob(Mail::class, ['mail' => $mail->toString()]);
223
224
        return (new Response())->setCode(204);
225
    }
226
227
    /**
228
     * @api {post} /api/v1/node/subscribe Subscribe for node updates
229
     * @apiVersion 1.0.0
230
     * @apiName get
231
     * @apiGroup App\Notification
232
     * @apiPermission none
233
     * @apiDescription Receive node updates
234
     * @apiUse _getNodes
235
     * @apiUse _multiError
236
     *
237
     * @apiExample (cURL) exmaple:
238
     * curl -XPOST "https://SERVER/api/v1/node/subscribe"
239
     *
240
     * @apiSuccessExample {string} Success-Response:
241
     * HTTP/1.1 204 No Content
242
     *
243
     * @param null|mixed $id
244
     * @param null|mixed $p
245
     */
246
    public function postSubscribe($id = null, $p = null, bool $subscribe = true)
247
    {
248
        if (is_array($id) || is_array($p)) {
249
            foreach ($this->fs->findNodesById($id) as $node) {
250
                try {
251
                    $this->notifier->subscribe($this->fs->getNode($id, $p), $subscribe);
252
                } catch (\Exception $e) {
253
                    $failures[] = [
0 ignored issues
show
Coding Style Comprehensibility introduced by
$failures was never initialized. Although not strictly required by PHP, it is generally a good practice to add $failures = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
254
                        'id' => (string) $node->getId(),
255
                        'name' => $node->getName(),
256
                        'error' => get_class($e),
257
                        'message' => $e->getMessage(),
258
                        'code' => $e->getCode(),
259
                    ];
260
261
                    $this->logger->debug('failed subscribe node in multi node request ['.$node->getId().']', [
262
                        'category' => get_class($this),
263
                        'exception' => $e,
264
                    ]);
265
                }
266
            }
267
268
            if (empty($failures)) {
269
                return (new Response())->setCode(204);
270
            }
271
272
            return (new Response())->setcode(400)->setBody($failures);
273
        }
274
275
        $this->notifier->subscribe($this->fs->getNode($id, $p), $subscribe);
276
277
        return (new Response())->setCode(204);
278
    }
279
}
280