Passed
Push — master ( eb2b1b...a761e5 )
by Morris
14:02 queued 11s
created

File::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 18
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 8
nc 1
nop 8
dl 0
loc 18
rs 10
c 0
b 0
f 0

How to fix   Many Parameters   

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

1
<?php
2
3
declare(strict_types=1);
4
/**
5
 * @copyright Copyright (c) 2019 Arthur Schiwon <[email protected]>
6
 *
7
 * @author Arthur Schiwon <[email protected]>
8
 *
9
 * @license GNU AGPL version 3 or any later version
10
 *
11
 * This program is free software: you can redistribute it and/or modify
12
 * it under the terms of the GNU Affero General Public License as
13
 * published by the Free Software Foundation, either version 3 of the
14
 * License, or (at your option) any later version.
15
 *
16
 * This program is distributed in the hope that it will be useful,
17
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19
 * GNU Affero General Public License for more details.
20
 *
21
 * You should have received a copy of the GNU Affero General Public License
22
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
23
 *
24
 */
25
26
namespace OCA\WorkflowEngine\Entity;
27
28
use OCP\EventDispatcher\Event;
29
use OCP\EventDispatcher\GenericEvent;
30
use OCP\Files\InvalidPathException;
31
use OCP\Files\IRootFolder;
32
use OCP\Files\Node;
33
use OCP\Files\NotFoundException;
34
use OCP\IL10N;
35
use OCP\ILogger;
36
use OCP\IURLGenerator;
37
use OCP\IUser;
38
use OCP\IUserManager;
39
use OCP\IUserSession;
40
use OCP\Share\IManager as ShareManager;
41
use OCP\SystemTag\ISystemTag;
42
use OCP\SystemTag\ISystemTagManager;
43
use OCP\SystemTag\MapperEvent;
44
use OCP\WorkflowEngine\EntityContext\IContextPortation;
45
use OCP\WorkflowEngine\EntityContext\IDisplayText;
46
use OCP\WorkflowEngine\EntityContext\IIcon;
47
use OCP\WorkflowEngine\EntityContext\IUrl;
48
use OCP\WorkflowEngine\GenericEntityEvent;
49
use OCP\WorkflowEngine\IEntity;
50
use OCP\WorkflowEngine\IRuleMatcher;
51
52
class File implements IEntity, IDisplayText, IUrl, IIcon, IContextPortation {
53
	private const EVENT_NAMESPACE = '\OCP\Files::';
54
55
	/** @var IL10N */
56
	protected $l10n;
57
	/** @var IURLGenerator */
58
	protected $urlGenerator;
59
	/** @var IRootFolder */
60
	protected $root;
61
	/** @var ILogger */
62
	protected $logger;
63
	/** @var string */
64
	protected $eventName;
65
	/** @var Event */
66
	protected $event;
67
	/** @var ShareManager */
68
	private $shareManager;
69
	/** @var IUserSession */
70
	private $userSession;
71
	/** @var ISystemTagManager */
72
	private $tagManager;
73
	/** @var ?Node */
74
	private $node;
75
	/** @var ?IUser */
76
	private $actingUser = null;
77
	/** @var IUserManager */
78
	private $userManager;
79
80
	public function __construct(
81
		IL10N $l10n,
82
		IURLGenerator $urlGenerator,
83
		IRootFolder $root,
84
		ILogger $logger,
85
		ShareManager $shareManager,
86
		IUserSession $userSession,
87
		ISystemTagManager $tagManager,
88
		IUserManager $userManager
89
	) {
90
		$this->l10n = $l10n;
91
		$this->urlGenerator = $urlGenerator;
92
		$this->root = $root;
93
		$this->logger = $logger;
94
		$this->shareManager = $shareManager;
95
		$this->userSession = $userSession;
96
		$this->tagManager = $tagManager;
97
		$this->userManager = $userManager;
98
	}
99
100
	public function getName(): string {
101
		return $this->l10n->t('File');
102
	}
103
104
	public function getIcon(): string {
105
		return $this->urlGenerator->imagePath('core', 'categories/files.svg');
106
	}
107
108
	public function getEvents(): array {
109
		return [
110
			new GenericEntityEvent($this->l10n->t('File created'), self::EVENT_NAMESPACE . 'postCreate'),
111
			new GenericEntityEvent($this->l10n->t('File updated'), self::EVENT_NAMESPACE . 'postWrite'),
112
			new GenericEntityEvent($this->l10n->t('File renamed'), self::EVENT_NAMESPACE . 'postRename'),
113
			new GenericEntityEvent($this->l10n->t('File deleted'), self::EVENT_NAMESPACE . 'postDelete'),
114
			new GenericEntityEvent($this->l10n->t('File accessed'), self::EVENT_NAMESPACE . 'postTouch'),
115
			new GenericEntityEvent($this->l10n->t('File copied'), self::EVENT_NAMESPACE . 'postCopy'),
116
			new GenericEntityEvent($this->l10n->t('Tag assigned'), MapperEvent::EVENT_ASSIGN),
117
		];
118
	}
119
120
	public function prepareRuleMatcher(IRuleMatcher $ruleMatcher, string $eventName, Event $event): void {
121
		if (!$event instanceof GenericEvent && !$event instanceof MapperEvent) {
122
			return;
123
		}
124
		$this->eventName = $eventName;
125
		$this->event = $event;
126
		$this->actingUser = $this->actingUser ?? $this->userSession->getUser();
127
		try {
128
			$node = $this->getNode();
129
			$ruleMatcher->setEntitySubject($this, $node);
130
			$ruleMatcher->setFileInfo($node->getStorage(), $node->getInternalPath());
131
		} catch (NotFoundException $e) {
132
			// pass
133
		}
134
	}
135
136
	public function isLegitimatedForUserId(string $uid): bool {
137
		try {
138
			$node = $this->getNode();
139
			if ($node->getOwner()->getUID() === $uid) {
140
				return true;
141
			}
142
			$acl = $this->shareManager->getAccessList($node, true, true);
143
			return array_key_exists($uid, $acl['users']);
144
		} catch (NotFoundException $e) {
145
			return false;
146
		}
147
	}
148
149
	/**
150
	 * @throws NotFoundException
151
	 */
152
	protected function getNode(): Node {
153
		if ($this->node) {
154
			return $this->node;
155
		}
156
		if (!$this->event instanceof GenericEvent && !$this->event instanceof MapperEvent) {
157
			throw new NotFoundException();
158
		}
159
		switch ($this->eventName) {
160
			case self::EVENT_NAMESPACE . 'postCreate':
161
			case self::EVENT_NAMESPACE . 'postWrite':
162
			case self::EVENT_NAMESPACE . 'postDelete':
163
			case self::EVENT_NAMESPACE . 'postTouch':
164
				return $this->event->getSubject();
0 ignored issues
show
Bug introduced by
The method getSubject() does not exist on OCP\SystemTag\MapperEvent. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

164
				return $this->event->/** @scrutinizer ignore-call */ getSubject();

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
165
			case self::EVENT_NAMESPACE . 'postRename':
166
			case self::EVENT_NAMESPACE . 'postCopy':
167
				return $this->event->getSubject()[1];
168
			case MapperEvent::EVENT_ASSIGN:
169
				if (!$this->event instanceof MapperEvent || $this->event->getObjectType() !== 'files') {
170
					throw new NotFoundException();
171
				}
172
				$nodes = $this->root->getById((int)$this->event->getObjectId());
173
				if (is_array($nodes) && isset($nodes[0])) {
174
					$this->node = $nodes[0];
175
					return $this->node;
176
				}
177
				break;
178
		}
179
		throw new NotFoundException();
180
	}
181
182
	public function getDisplayText(int $verbosity = 0): string {
183
		try {
184
			$node = $this->getNode();
185
		} catch (NotFoundException $e) {
186
			return '';
187
		}
188
189
		$options = [
190
			$this->actingUser ? $this->actingUser->getDisplayName() : $this->l10n->t('Someone'),
191
			$node->getName()
192
		];
193
194
		switch ($this->eventName) {
195
			case self::EVENT_NAMESPACE . 'postCreate':
196
				return $this->l10n->t('%s created %s', $options);
197
			case self::EVENT_NAMESPACE . 'postWrite':
198
				return $this->l10n->t('%s modified %s', $options);
199
			case self::EVENT_NAMESPACE . 'postDelete':
200
				return $this->l10n->t('%s deleted %s', $options);
201
			case self::EVENT_NAMESPACE . 'postTouch':
202
				return $this->l10n->t('%s accessed %s', $options);
203
			case self::EVENT_NAMESPACE . 'postRename':
204
				return $this->l10n->t('%s renamed %s', $options);
205
			case self::EVENT_NAMESPACE . 'postCopy':
206
				return $this->l10n->t('%s copied %s', $options);
207
			case MapperEvent::EVENT_ASSIGN:
208
				$tagNames = [];
209
				if ($this->event instanceof MapperEvent) {
210
					$tagIDs = $this->event->getTags();
211
					$tagObjects = $this->tagManager->getTagsByIds($tagIDs);
212
					foreach ($tagObjects as $systemTag) {
213
						/** @var ISystemTag $systemTag */
214
						if ($systemTag->isUserVisible()) {
215
							$tagNames[] = $systemTag->getName();
216
						}
217
					}
218
				}
219
				$filename = array_pop($options);
220
				$tagString = implode(', ', $tagNames);
221
				if ($tagString === '') {
222
					return '';
223
				}
224
				array_push($options, $tagString, $filename);
225
				return $this->l10n->t('%s assigned %s to %s', $options);
0 ignored issues
show
Bug Best Practice introduced by
In this branch, the function will implicitly return null which is incompatible with the type-hinted return string. Consider adding a return statement or allowing null as return value.

For hinted functions/methods where all return statements with the correct type are only reachable via conditions, ?null? gets implicitly returned which may be incompatible with the hinted type. Let?s take a look at an example:

interface ReturnsInt {
    public function returnsIntHinted(): int;
}

class MyClass implements ReturnsInt {
    public function returnsIntHinted(): int
    {
        if (foo()) {
            return 123;
        }
        // here: null is implicitly returned
    }
}
Loading history...
226
		}
227
	}
228
229
	public function getUrl(): string {
230
		try {
231
			return $this->urlGenerator->linkToRouteAbsolute('files.viewcontroller.showFile', ['fileid' => $this->getNode()->getId()]);
232
		} catch (InvalidPathException $e) {
233
			return '';
234
		} catch (NotFoundException $e) {
235
			return '';
236
		}
237
	}
238
239
	/**
240
	 * @inheritDoc
241
	 */
242
	public function exportContextIDs(): array {
243
		$nodeOwner = $this->getNode()->getOwner();
244
		$actingUserId = null;
245
		if ($this->actingUser instanceof IUser) {
246
			$actingUserId = $this->actingUser->getUID();
247
		} elseif ($this->userSession->getUser() instanceof IUser) {
248
			$actingUserId = $this->userSession->getUser()->getUID();
249
		}
250
		return [
251
			'eventName' => $this->eventName,
252
			'nodeId' => $this->getNode()->getId(),
253
			'nodeOwnerId' => $nodeOwner ? $nodeOwner->getUID() : null,
0 ignored issues
show
introduced by
$nodeOwner is of type OCP\IUser, thus it always evaluated to true.
Loading history...
254
			'actingUserId' => $actingUserId,
255
		];
256
	}
257
258
	/**
259
	 * @inheritDoc
260
	 */
261
	public function importContextIDs(array $contextIDs): void {
262
		$this->eventName = $contextIDs['eventName'];
263
		if ($contextIDs['nodeOwnerId'] !== null) {
264
			$userFolder = $this->root->getUserFolder($contextIDs['nodeOwnerId']);
265
			$nodes = $userFolder->getById($contextIDs['nodeId']);
266
		} else {
267
			$nodes = $this->root->getById($contextIDs['nodeId']);
268
		}
269
		$this->node = $nodes[0] ?? null;
270
		if ($contextIDs['actingUserId']) {
271
			$this->actingUser = $this->userManager->get($contextIDs['actingUserId']);
272
		}
273
	}
274
275
	/**
276
	 * @inheritDoc
277
	 */
278
	public function getIconUrl(): string {
279
		return $this->getIcon();
280
	}
281
}
282