Completed
Push — master ( 4f34f2...9208b7 )
by Roeland
8s
created

PageController::add()   B

Complexity

Conditions 5
Paths 4

Size

Total Lines 32
Code Lines 21

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 20
CRAP Score 5

Importance

Changes 0
Metric Value
dl 0
loc 32
ccs 20
cts 20
cp 1
rs 8.439
c 0
b 0
f 0
cc 5
eloc 21
nc 4
nop 6
crap 5
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\TemplateResponse;
30
use OCP\AppFramework\Http\Response;
31
use OCP\AppFramework\Controller;
32
use OCP\BackgroundJob\IJobList;
33
use OCP\IConfig;
34
use OCP\IDBConnection;
35
use OCP\IGroupManager;
36
use OCP\IL10N;
37
use OCP\IRequest;
38
use OCP\IUser;
39
use OCP\IUserManager;
40
use OCP\IUserSession;
41
42
class PageController extends Controller {
43
	/** @var int */
44
	const PAGE_LIMIT = 5;
45
46
	/** @var IJobList */
47
	protected $jobList;
48
49
	/** @var IDBConnection */
50
	protected $connection;
51
52
	/** @var IGroupManager */
53
	protected $groupManager;
54
55
	/** @var IUserManager */
56
	protected $userManager;
57
58
	/** @var IL10N */
59
	protected $l;
60
61
	/** @var Manager */
62
	protected $manager;
63
64
	/** @var IConfig */
65
	protected $config;
66
67
	/** @var IUserSession */
68
	protected $userSession;
69
70
	/**
71
	 * @param string $AppName
72
	 * @param IRequest $request
73
	 * @param IDBConnection $connection
74
	 * @param IGroupManager $groupManager
75
	 * @param IUserManager $userManager
76
	 * @param IJobList $jobList
77
	 * @param IL10N $l
78
	 * @param Manager $manager
79
	 * @param IConfig $config
80
	 * @param IUserSession $userSession
81
	 */
82 24
	public function __construct($AppName,
83
								IRequest $request,
84
								IDBConnection $connection,
85
								IGroupManager $groupManager,
86
								IUserManager $userManager,
87
								IJobList $jobList,
88
								IL10N $l,
89
								Manager $manager,
90
								IConfig $config,
91
								IUserSession $userSession) {
92 24
		parent::__construct($AppName, $request);
93
94 24
		$this->connection = $connection;
95 24
		$this->groupManager = $groupManager;
96 24
		$this->userManager = $userManager;
97 24
		$this->jobList = $jobList;
98 24
		$this->l = $l;
99 24
		$this->manager = $manager;
100 24
		$this->config = $config;
101 24
		$this->userSession = $userSession;
102 24
	}
103
104
	/**
105
	 * @NoAdminRequired
106
	 * @NoCSRFRequired
107
	 *
108
	 * @param int $offset
109
	 * @return JSONResponse
110
	 */
111 6
	public function get($offset = 0) {
112 6
		$rows = $this->manager->getAnnouncements(self::PAGE_LIMIT, $offset);
113
114 6
		$announcements = [];
115 6
		foreach ($rows as $row) {
116 3
			$displayName = $row['author'];
117 3
			$user = $this->userManager->get($displayName);
118 3
			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...
119 1
				$displayName = $user->getDisplayName();
120
			}
121
122 3
			$row['author_id'] = $row['author'];
123 3
			$row['author'] = $displayName;
124
125 3
			$announcements[] = $row;
126
		}
127
128 6
		return new JSONResponse($announcements);
129
	}
130
131
	/**
132
	 * @NoAdminRequired
133
	 *
134
	 * @param string $subject
135
	 * @param string $message
136
	 * @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...
137
	 * @param bool $activities
138
	 * @param bool $notifications
139
	 * @param bool $comments
140
	 * @return JSONResponse
141
	 */
142 8
	public function add($subject, $message, array $groups, $activities, $notifications, $comments) {
143 8
		if (!$this->manager->checkIsAdmin()) {
144 1
			return new JSONResponse(
145 1
				['message' => 'Logged in user must be an admin'],
146 1
				Http::STATUS_FORBIDDEN
147
			);
148
		}
149
150 7
		$timeStamp = time();
151
		try {
152 7
			$announcement = $this->manager->announce($subject, $message, $this->userSession->getUser()->getUID(), $timeStamp, $groups, $comments);
153 2
		} catch (\InvalidArgumentException $e) {
154 2
			return new JSONResponse(
155 2
				['error' => (string)$this->l->t('The subject is too long or empty')],
156 2
				Http::STATUS_BAD_REQUEST
157
			);
158
		}
159
160 5
		if ($activities || $notifications) {
161 3
			$this->jobList->add('OCA\AnnouncementCenter\BackgroundJob', [
162 3
				'id' => $announcement['id'],
163 3
				'activities' => $activities,
164 3
				'notifications' => $notifications,
165
			]);
166
		}
167
168 5
		$announcement['notifications'] = $notifications;
169 5
		$announcement['author_id'] = $announcement['author'];
170 5
		$announcement['author'] = $this->userManager->get($announcement['author_id'])->getDisplayName();
171
172 5
		return new JSONResponse($announcement);
173
	}
174
175
	/**
176
	 * @NoAdminRequired
177
	 *
178
	 * @param int $id
179
	 * @return Response
180
	 */
181 2 View Code Duplication
	public function delete($id) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
182 2
		if (!$this->manager->checkIsAdmin()) {
183 1
			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...
184 1
				['message' => 'Logged in user must be an admin'],
185 1
				Http::STATUS_FORBIDDEN
186
			);
187
		}
188
189 1
		$this->manager->delete($id);
190
191 1
		return new Response();
192
	}
193
194
	/**
195
	 * @NoAdminRequired
196
	 *
197
	 * @param int $id
198
	 * @return Response
199
	 */
200 View Code Duplication
	public function removeNotifications($id) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
201
		if (!$this->manager->checkIsAdmin()) {
202
			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...er::removeNotifications 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...
203
				['message' => 'Logged in user must be an admin'],
204
				Http::STATUS_FORBIDDEN
205
			);
206
		}
207
208
		$this->manager->removeNotifications($id);
209
210
		return new Response();
211
	}
212
213
	/**
214
	 * @NoAdminRequired
215
	 * @NoCSRFRequired
216
	 *
217
	 * @param int $announcement
218
	 * @return TemplateResponse
219
	 */
220 3
	public function index($announcement = 0) {
221 3
		if ($announcement) {
222
			$this->manager->markNotificationRead($announcement);
223
		}
224
225 3
		return new TemplateResponse('announcementcenter', 'main', [
226 3
			'isAdmin'	=> $this->manager->checkIsAdmin(),
227 3
			'createActivities' => $this->config->getAppValue('announcementcenter', 'create_activities', 'yes') === 'yes',
228 3
			'createNotifications' => $this->config->getAppValue('announcementcenter', 'create_notifications', 'yes') === 'yes',
229 3
			'allowComments' => $this->config->getAppValue('announcementcenter', 'allow_comments', 'yes') === 'yes',
230
		]);
231
	}
232
233
	/**
234
	 * @NoAdminRequired
235
	 *
236
	 * @param string $pattern
237
	 * @return JSONResponse
238
	 */
239 3
	public function searchGroups($pattern) {
240 3
		if (!$this->manager->checkIsAdmin()) {
241 1
			return new JSONResponse(
242 1
				['message' => 'Logged in user must be an admin'],
243 1
				Http::STATUS_FORBIDDEN
244
			);
245
		}
246
247 2
		$groups = $this->groupManager->search($pattern, 10);
248 2
		$gids = [];
249 2
		foreach ($groups as $group) {
250 1
			$gids[] = $group->getGID();
251
		}
252
253 2
		return new JSONResponse($gids);
254
	}
255
}
256