Completed
Pull Request — master (#44)
by Joas
02:42
created

PageController::markProcessed()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 12
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 6

Importance

Changes 0
Metric Value
dl 0
loc 12
ccs 0
cts 11
cp 0
rs 9.4285
c 0
b 0
f 0
cc 2
eloc 10
nc 2
nop 1
crap 6
1
<?php
2
/**
3
 * @copyright Copyright (c) 2016, Joas Schilling <[email protected]>
4
 *
5
 * @author Joas Schilling <[email protected]>
6
 *
7
 * @license GNU AGPL version 3 or any later version
8
 *
9
 * This program is free software: you can redistribute it and/or modify
10
 * it under the terms of the GNU Affero General Public License as
11
 * published by the Free Software Foundation, either version 3 of the
12
 * License, or (at your option) any later version.
13
 *
14
 * This program is distributed in the hope that it will be useful,
15
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17
 * GNU Affero General Public License for more details.
18
 *
19
 * You should have received a copy of the GNU Affero General Public License
20
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
21
 *
22
 */
23
24
namespace OCA\AnnouncementCenter\Controller;
25
26
use OCA\AnnouncementCenter\Manager;
27
use OCP\AppFramework\Http;
28
use OCP\AppFramework\Http\JSONResponse;
29
use OCP\AppFramework\Http\NotFoundResponse;
30
use OCP\AppFramework\Http\RedirectResponse;
31
use OCP\AppFramework\Http\Response;
32
use OCP\AppFramework\Http\TemplateResponse;
33
use OCP\AppFramework\Controller;
34
use OCP\BackgroundJob\IJobList;
35
use OCP\Comments\IComment;
36
use OCP\Comments\ICommentsManager;
37
use OCP\IConfig;
38
use OCP\IDBConnection;
39
use OCP\IGroupManager;
40
use OCP\IL10N;
41
use OCP\IRequest;
42
use OCP\IURLGenerator;
43
use OCP\IUser;
44
use OCP\IUserManager;
45
use OCP\IUserSession;
46
use OCP\Notification\IManager as INotificationManager;
47
48
class PageController extends Controller {
49
	/** @var int */
50
	const PAGE_LIMIT = 5;
51
52
	/** @var IJobList */
53
	protected $jobList;
54
55
	/** @var IDBConnection */
56
	protected $connection;
57
58
	/** @var IGroupManager */
59
	protected $groupManager;
60
61
	/** @var IUserManager */
62
	protected $userManager;
63
64
	/** @var ICommentsManager */
65
	protected $commentsManager;
66
67
	/** @var INotificationManager */
68
	protected $notificationManager;
69
70
	/** @var IL10N */
71
	protected $l;
72
73
	/** @var Manager */
74
	protected $manager;
75
76
	/** @var IConfig */
77
	protected $config;
78
79
	/** @var IURLGenerator */
80
	protected $urlGenerator;
81
82
	/** @var IUserSession */
83
	protected $userSession;
84
85
	/**
86
	 * @param string $AppName
87
	 * @param IRequest $request
88
	 * @param IDBConnection $connection
89
	 * @param IGroupManager $groupManager
90
	 * @param IUserManager $userManager
91
	 * @param ICommentsManager $commentsManager
92
	 * @param INotificationManager $notificationManager
93
	 * @param IJobList $jobList
94
	 * @param IL10N $l
95
	 * @param Manager $manager
96
	 * @param IConfig $config
97
	 * @param IURLGenerator $urlGenerator
98
	 * @param IUserSession $userSession
99
	 */
100 1
	public function __construct($AppName,
101
								IRequest $request,
102
								IDBConnection $connection,
103
								IGroupManager $groupManager,
104
								IUserManager $userManager,
105
								ICommentsManager $commentsManager,
106
								INotificationManager $notificationManager,
107
								IJobList $jobList,
108
								IL10N $l,
109
								Manager $manager,
110
								IConfig $config,
111
								IURLGenerator $urlGenerator,
112
								IUserSession $userSession) {
113 1
		parent::__construct($AppName, $request);
114
115 1
		$this->connection = $connection;
116 1
		$this->groupManager = $groupManager;
117 1
		$this->userManager = $userManager;
118 1
		$this->commentsManager = $commentsManager;
119 1
		$this->notificationManager = $notificationManager;
120 1
		$this->jobList = $jobList;
121 1
		$this->l = $l;
122 1
		$this->manager = $manager;
123 1
		$this->config = $config;
124 1
		$this->urlGenerator = $urlGenerator;
125 1
		$this->userSession = $userSession;
126 1
	}
127
128
	/**
129
	 * @NoAdminRequired
130
	 * @NoCSRFRequired
131
	 *
132
	 * @param int $offset
133
	 * @return JSONResponse
134
	 */
135
	public function get($offset = 0) {
136
		$rows = $this->manager->getAnnouncements(self::PAGE_LIMIT, $offset);
137
138
		$announcements = [];
139
		foreach ($rows as $row) {
140
			$displayName = $row['author'];
141
			$user = $this->userManager->get($displayName);
142
			if ($user instanceof IUser) {
0 ignored issues
show
Bug introduced by
The class OCP\IUser does not exist. Did you forget a USE statement, or did you not list all dependencies?

This error could be the result of:

1. Missing dependencies

PHP Analyzer uses your composer.json file (if available) to determine the dependencies of your project and to determine all the available classes and functions. It expects the composer.json to be in the root folder of your repository.

Are you sure this class is defined by one of your dependencies, or did you maybe not list a dependency in either the require or require-dev section?

2. Missing use statement

PHP does not complain about undefined classes in ìnstanceof checks. For example, the following PHP code will work perfectly fine:

if ($x instanceof DoesNotExist) {
    // Do something.
}

If you have not tested against this specific condition, such errors might go unnoticed.

Loading history...
143
				$displayName = $user->getDisplayName();
144
			}
145
146
			$announcements[] = [
147
				'id'		=> $row['id'],
148
				'author'	=> $displayName,
149
				'author_id'	=> $row['author'],
150
				'time'		=> $row['time'],
151
				'subject'	=> $row['subject'],
152
				'message'	=> $row['message'],
153
				'groups'	=> $row['groups'],
154
				'comments'	=> $row['comments'],
155
			];
156
		}
157
158
		return new JSONResponse($announcements);
159
	}
160
161
	/**
162
	 * @NoAdminRequired
163
	 *
164
	 * @param string $subject
165
	 * @param string $message
166
	 * @param string[] $groups,
0 ignored issues
show
Documentation introduced by
There is no parameter named $groups,. Did you maybe mean $groups?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function. It has, however, found a similar but not annotated parameter which might be a good fit.

Consider the following example. The parameter $ireland is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $ireland
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was changed, but the annotation was not.

Loading history...
167
	 * @param bool $activities
168
	 * @param bool $notifications
169
	 * @param bool $comments
170
	 * @return JSONResponse
171
	 */
172
	public function add($subject, $message, array $groups, $activities, $notifications, $comments) {
173
		if (!$this->manager->checkIsAdmin()) {
174
			return new JSONResponse(
175
				['message' => 'Logged in user must be an admin'],
176
				Http::STATUS_FORBIDDEN
177
			);
178
		}
179
180
		$timeStamp = time();
181
		try {
182
			$announcement = $this->manager->announce($subject, $message, $this->userSession->getUser()->getUID(), $timeStamp, $groups, $comments);
183
		} catch (\InvalidArgumentException $e) {
184
			return new JSONResponse(
185
				['error' => (string)$this->l->t('The subject is too long or empty')],
186
				Http::STATUS_BAD_REQUEST
187
			);
188
		}
189
190
		if ($activities || $notifications) {
191
			$this->jobList->add('OCA\AnnouncementCenter\BackgroundJob', [
192
				'id' => $announcement['id'],
193
				'activities' => $activities,
194
				'notifications' => $notifications,
195
			]);
196
		}
197
198
		$announcement['author_id'] = $announcement['author'];
199
		$announcement['author'] = $this->userManager->get($announcement['author_id'])->getDisplayName();
200
201
		return new JSONResponse($announcement);
202
	}
203
204
	/**
205
	 * @NoAdminRequired
206
	 *
207
	 * @param int $id
208
	 * @return Response
209
	 */
210
	public function delete($id) {
211
		if (!$this->manager->checkIsAdmin()) {
212
			return new JSONResponse(
0 ignored issues
show
Bug Best Practice introduced by
The return type of return new \OCP\AppFrame...ttp::STATUS_FORBIDDEN); (OCP\AppFramework\Http\JSONResponse) is incompatible with the return type documented by OCA\AnnouncementCenter\C...\PageController::delete of type OCP\AppFramework\Http\Response.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
213
				['message' => 'Logged in user must be an admin'],
214
				Http::STATUS_FORBIDDEN
215
			);
216
		}
217
218
		$this->manager->delete($id);
219
220
		return new Response();
221
	}
222
223
	/**
224
	 * @NoAdminRequired
225
	 * @NoCSRFRequired
226
	 *
227
	 * @author Arthur Schiwon <[email protected]>
228
	 * @param string $id
229
	 * @return RedirectResponse|NotFoundResponse
230
	 */
231
	public function followComment($id) {
232
		try {
233
			$comment = $this->commentsManager->get($id);
234
			if($comment->getObjectType() !== 'announcement') {
235
				return new NotFoundResponse();
236
			}
237
238
			try {
239
				$this->manager->getAnnouncement($comment->getObjectId());
240
			} catch (\InvalidArgumentException $e) {
241
				$this->markProcessed($comment);
242
				return new NotFoundResponse();
243
			}
244
245
			$url = $this->urlGenerator->linkToRouteAbsolute(
246
				'announcementcenter.page.index'
247
			);
248
			$url .= '#' . $comment->getObjectId() . '-comments';
249
250
			$this->markProcessed($comment);
251
252
			return new RedirectResponse($url);
253
		} catch (\Exception $e) {
254
			return new NotFoundResponse();
255
		}
256
	}
257
258
259
	/**
260
	 * Marks the notification about a comment as processed
261
	 *
262
	 * @author Arthur Schiwon <[email protected]>
263
	 * @param IComment $comment
264
	 */
265
	protected function markProcessed(IComment $comment) {
266
		$user = $this->userSession->getUser();
267
		if(is_null($user)) {
268
			return;
269
		}
270
		$notification = $this->notificationManager->createNotification();
271
		$notification->setApp('announcementcenter')
272
			->setObject('comment', $comment->getId())
273
			->setSubject('mention')
274
			->setUser($user->getUID());
275
		$this->notificationManager->markProcessed($notification);
276
	}
277
278
	/**
279
	 * @NoAdminRequired
280
	 * @NoCSRFRequired
281
	 *
282
	 * @return TemplateResponse
283
	 */
284
	public function index() {
285
		return new TemplateResponse('announcementcenter', 'main', [
286
			'isAdmin'	=> $this->manager->checkIsAdmin(),
287
			'createActivities' => $this->config->getAppValue('announcementcenter', 'create_activities', 'yes') === 'yes',
288
			'createNotifications' => $this->config->getAppValue('announcementcenter', 'create_notifications', 'yes') === 'yes',
289
			'allowComments' => $this->config->getAppValue('announcementcenter', 'allow_comments', 'yes') === 'yes',
290
		]);
291
	}
292
293
	/**
294
	 * @NoAdminRequired
295
	 *
296
	 * @param string $pattern
297
	 * @return JSONResponse
298
	 */
299
	public function searchGroups($pattern) {
300
		if (!$this->manager->checkIsAdmin()) {
301
			return new JSONResponse(
302
				['message' => 'Logged in user must be an admin'],
303
				Http::STATUS_FORBIDDEN
304
			);
305
		}
306
307
		$groups = $this->groupManager->search($pattern, 10);
308
		$gids = [];
309
		foreach ($groups as $group) {
310
			$gids[] = $group->getGID();
311
		}
312
313
		return new JSONResponse($gids);
314
	}
315
}
316