| Total Complexity | 70 |
| Total Lines | 533 |
| Duplicated Lines | 0 % |
| Changes | 0 | ||
Complex classes like ShareController often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.
Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.
While breaking up the class, it is a good idea to analyze how other classes use ShareController, and based on these observations, apply Extract Interface, too.
| 1 | <?php |
||
| 88 | class ShareController extends AuthPublicShareController { |
||
| 89 | protected IConfig $config; |
||
| 90 | protected IUserManager $userManager; |
||
| 91 | protected ILogger $logger; |
||
| 92 | protected \OCP\Activity\IManager $activityManager; |
||
| 93 | protected IPreview $previewManager; |
||
| 94 | protected IRootFolder $rootFolder; |
||
| 95 | protected FederatedShareProvider $federatedShareProvider; |
||
| 96 | protected IAccountManager $accountManager; |
||
| 97 | protected IEventDispatcher $eventDispatcher; |
||
| 98 | protected IL10N $l10n; |
||
| 99 | protected Defaults $defaults; |
||
| 100 | protected ShareManager $shareManager; |
||
| 101 | protected ISecureRandom $secureRandom; |
||
| 102 | protected ?Share\IShare $share = null; |
||
| 103 | private IPublicShareTemplateFactory $publicShareTemplateFactory; |
||
| 104 | |||
| 105 | public function __construct( |
||
| 106 | string $appName, |
||
| 107 | IRequest $request, |
||
| 108 | IConfig $config, |
||
| 109 | IURLGenerator $urlGenerator, |
||
| 110 | IUserManager $userManager, |
||
| 111 | ILogger $logger, |
||
| 112 | \OCP\Activity\IManager $activityManager, |
||
| 113 | ShareManager $shareManager, |
||
| 114 | ISession $session, |
||
| 115 | IPreview $previewManager, |
||
| 116 | IRootFolder $rootFolder, |
||
| 117 | FederatedShareProvider $federatedShareProvider, |
||
| 118 | IAccountManager $accountManager, |
||
| 119 | IEventDispatcher $eventDispatcher, |
||
| 120 | IL10N $l10n, |
||
| 121 | ISecureRandom $secureRandom, |
||
| 122 | Defaults $defaults, |
||
| 123 | IPublicShareTemplateFactory $publicShareTemplateFactory |
||
| 124 | ) { |
||
| 125 | parent::__construct($appName, $request, $session, $urlGenerator); |
||
| 126 | |||
| 127 | $this->config = $config; |
||
| 128 | $this->userManager = $userManager; |
||
| 129 | $this->logger = $logger; |
||
| 130 | $this->activityManager = $activityManager; |
||
| 131 | $this->previewManager = $previewManager; |
||
| 132 | $this->rootFolder = $rootFolder; |
||
| 133 | $this->federatedShareProvider = $federatedShareProvider; |
||
| 134 | $this->accountManager = $accountManager; |
||
| 135 | $this->eventDispatcher = $eventDispatcher; |
||
| 136 | $this->l10n = $l10n; |
||
| 137 | $this->secureRandom = $secureRandom; |
||
| 138 | $this->defaults = $defaults; |
||
| 139 | $this->shareManager = $shareManager; |
||
| 140 | $this->publicShareTemplateFactory = $publicShareTemplateFactory; |
||
| 141 | } |
||
| 142 | |||
| 143 | public const SHARE_ACCESS = 'access'; |
||
| 144 | public const SHARE_AUTH = 'auth'; |
||
| 145 | public const SHARE_DOWNLOAD = 'download'; |
||
| 146 | |||
| 147 | /** |
||
| 148 | * @PublicPage |
||
| 149 | * @NoCSRFRequired |
||
| 150 | * |
||
| 151 | * Show the authentication page |
||
| 152 | * The form has to submit to the authenticate method route |
||
| 153 | */ |
||
| 154 | public function showAuthenticate(): TemplateResponse { |
||
| 155 | $templateParameters = ['share' => $this->share]; |
||
| 156 | |||
| 157 | $this->eventDispatcher->dispatchTyped(new BeforeTemplateRenderedEvent($this->share, BeforeTemplateRenderedEvent::SCOPE_PUBLIC_SHARE_AUTH)); |
||
| 158 | |||
| 159 | $response = new TemplateResponse('core', 'publicshareauth', $templateParameters, 'guest'); |
||
| 160 | if ($this->share->getSendPasswordByTalk()) { |
||
| 161 | $csp = new ContentSecurityPolicy(); |
||
| 162 | $csp->addAllowedConnectDomain('*'); |
||
| 163 | $csp->addAllowedMediaDomain('blob:'); |
||
| 164 | $response->setContentSecurityPolicy($csp); |
||
| 165 | } |
||
| 166 | |||
| 167 | return $response; |
||
| 168 | } |
||
| 169 | |||
| 170 | /** |
||
| 171 | * The template to show when authentication failed |
||
| 172 | */ |
||
| 173 | protected function showAuthFailed(): TemplateResponse { |
||
| 174 | $templateParameters = ['share' => $this->share, 'wrongpw' => true]; |
||
| 175 | |||
| 176 | $this->eventDispatcher->dispatchTyped(new BeforeTemplateRenderedEvent($this->share, BeforeTemplateRenderedEvent::SCOPE_PUBLIC_SHARE_AUTH)); |
||
| 177 | |||
| 178 | $response = new TemplateResponse('core', 'publicshareauth', $templateParameters, 'guest'); |
||
| 179 | if ($this->share->getSendPasswordByTalk()) { |
||
| 180 | $csp = new ContentSecurityPolicy(); |
||
| 181 | $csp->addAllowedConnectDomain('*'); |
||
| 182 | $csp->addAllowedMediaDomain('blob:'); |
||
| 183 | $response->setContentSecurityPolicy($csp); |
||
| 184 | } |
||
| 185 | |||
| 186 | return $response; |
||
| 187 | } |
||
| 188 | |||
| 189 | /** |
||
| 190 | * The template to show after user identification |
||
| 191 | */ |
||
| 192 | protected function showIdentificationResult(bool $success = false): TemplateResponse { |
||
| 193 | $templateParameters = ['share' => $this->share, 'identityOk' => $success]; |
||
| 194 | |||
| 195 | $this->eventDispatcher->dispatchTyped(new BeforeTemplateRenderedEvent($this->share, BeforeTemplateRenderedEvent::SCOPE_PUBLIC_SHARE_AUTH)); |
||
| 196 | |||
| 197 | $response = new TemplateResponse('core', 'publicshareauth', $templateParameters, 'guest'); |
||
| 198 | if ($this->share->getSendPasswordByTalk()) { |
||
| 199 | $csp = new ContentSecurityPolicy(); |
||
| 200 | $csp->addAllowedConnectDomain('*'); |
||
| 201 | $csp->addAllowedMediaDomain('blob:'); |
||
| 202 | $response->setContentSecurityPolicy($csp); |
||
| 203 | } |
||
| 204 | |||
| 205 | return $response; |
||
| 206 | } |
||
| 207 | |||
| 208 | /** |
||
| 209 | * Validate the identity token of a public share |
||
| 210 | * |
||
| 211 | * @param ?string $identityToken |
||
| 212 | * @return bool |
||
| 213 | */ |
||
| 214 | protected function validateIdentity(?string $identityToken = null): bool { |
||
| 215 | |||
| 216 | if ($this->share->getShareType() !== IShare::TYPE_EMAIL) { |
||
| 217 | return false; |
||
| 218 | } |
||
| 219 | |||
| 220 | if ($identityToken === null || $this->share->getSharedWith() === null) { |
||
| 221 | return false; |
||
| 222 | } |
||
| 223 | |||
| 224 | return $identityToken === $this->share->getSharedWith(); |
||
| 225 | } |
||
| 226 | |||
| 227 | /** |
||
| 228 | * Generates a password for the share, respecting any password policy defined |
||
| 229 | */ |
||
| 230 | protected function generatePassword(): void { |
||
| 231 | $event = new \OCP\Security\Events\GenerateSecurePasswordEvent(); |
||
| 232 | $this->eventDispatcher->dispatchTyped($event); |
||
| 233 | $password = $event->getPassword() ?? $this->secureRandom->generate(20); |
||
| 234 | |||
| 235 | $this->share->setPassword($password); |
||
| 236 | $this->shareManager->updateShare($this->share); |
||
| 237 | } |
||
| 238 | |||
| 239 | protected function verifyPassword(string $password): bool { |
||
| 240 | return $this->shareManager->checkPassword($this->share, $password); |
||
| 241 | } |
||
| 242 | |||
| 243 | protected function getPasswordHash(): string { |
||
| 244 | return $this->share->getPassword(); |
||
| 245 | } |
||
| 246 | |||
| 247 | public function isValidToken(): bool { |
||
| 248 | try { |
||
| 249 | $this->share = $this->shareManager->getShareByToken($this->getToken()); |
||
| 250 | } catch (ShareNotFound $e) { |
||
| 251 | return false; |
||
| 252 | } |
||
| 253 | |||
| 254 | return true; |
||
| 255 | } |
||
| 256 | |||
| 257 | protected function isPasswordProtected(): bool { |
||
| 258 | return $this->share->getPassword() !== null; |
||
| 259 | } |
||
| 260 | |||
| 261 | protected function authSucceeded() { |
||
| 262 | // For share this was always set so it is still used in other apps |
||
| 263 | $this->session->set('public_link_authenticated', (string)$this->share->getId()); |
||
| 264 | } |
||
| 265 | |||
| 266 | protected function authFailed() { |
||
| 267 | $this->emitAccessShareHook($this->share, 403, 'Wrong password'); |
||
| 268 | $this->emitShareAccessEvent($this->share, self::SHARE_AUTH, 403, 'Wrong password'); |
||
| 269 | } |
||
| 270 | |||
| 271 | /** |
||
| 272 | * throws hooks when a share is attempted to be accessed |
||
| 273 | * |
||
| 274 | * @param \OCP\Share\IShare|string $share the Share instance if available, |
||
| 275 | * otherwise token |
||
| 276 | * @param int $errorCode |
||
| 277 | * @param string $errorMessage |
||
| 278 | * |
||
| 279 | * @throws \OCP\HintException |
||
| 280 | * @throws \OC\ServerNotAvailableException |
||
| 281 | * |
||
| 282 | * @deprecated use OCP\Files_Sharing\Event\ShareLinkAccessedEvent |
||
| 283 | */ |
||
| 284 | protected function emitAccessShareHook($share, int $errorCode = 200, string $errorMessage = '') { |
||
| 311 | } |
||
| 312 | } |
||
| 313 | |||
| 314 | /** |
||
| 315 | * Emit a ShareLinkAccessedEvent event when a share is accessed, downloaded, auth... |
||
| 316 | */ |
||
| 317 | protected function emitShareAccessEvent(IShare $share, string $step = '', int $errorCode = 200, string $errorMessage = ''): void { |
||
| 318 | if ($step !== self::SHARE_ACCESS && |
||
| 319 | $step !== self::SHARE_AUTH && |
||
| 320 | $step !== self::SHARE_DOWNLOAD) { |
||
| 321 | return; |
||
| 322 | } |
||
| 323 | $this->eventDispatcher->dispatchTyped(new ShareLinkAccessedEvent($share, $step, $errorCode, $errorMessage)); |
||
| 324 | } |
||
| 325 | |||
| 326 | /** |
||
| 327 | * Validate the permissions of the share |
||
| 328 | * |
||
| 329 | * @param Share\IShare $share |
||
| 330 | * @return bool |
||
| 331 | */ |
||
| 332 | private function validateShare(\OCP\Share\IShare $share) { |
||
| 333 | // If the owner is disabled no access to the link is granted |
||
| 334 | $owner = $this->userManager->get($share->getShareOwner()); |
||
| 335 | if ($owner === null || !$owner->isEnabled()) { |
||
| 336 | return false; |
||
| 337 | } |
||
| 338 | |||
| 339 | // If the initiator of the share is disabled no access is granted |
||
| 340 | $initiator = $this->userManager->get($share->getSharedBy()); |
||
| 341 | if ($initiator === null || !$initiator->isEnabled()) { |
||
| 342 | return false; |
||
| 343 | } |
||
| 344 | |||
| 345 | return $share->getNode()->isReadable() && $share->getNode()->isShareable(); |
||
| 346 | } |
||
| 347 | |||
| 348 | /** |
||
| 349 | * @PublicPage |
||
| 350 | * @NoCSRFRequired |
||
| 351 | * |
||
| 352 | * |
||
| 353 | * @param string $path |
||
| 354 | * @return TemplateResponse |
||
| 355 | * @throws NotFoundException |
||
| 356 | * @throws \Exception |
||
| 357 | */ |
||
| 358 | public function showShare($path = ''): TemplateResponse { |
||
| 359 | \OC_User::setIncognitoMode(true); |
||
| 360 | |||
| 361 | // Check whether share exists |
||
| 362 | try { |
||
| 363 | $share = $this->shareManager->getShareByToken($this->getToken()); |
||
| 364 | } catch (ShareNotFound $e) { |
||
| 365 | // The share does not exists, we do not emit an ShareLinkAccessedEvent |
||
| 366 | $this->emitAccessShareHook($this->getToken(), 404, 'Share not found'); |
||
| 367 | throw new NotFoundException(); |
||
| 368 | } |
||
| 369 | |||
| 370 | if (!$this->validateShare($share)) { |
||
| 371 | throw new NotFoundException(); |
||
| 372 | } |
||
| 373 | |||
| 374 | $shareNode = $share->getNode(); |
||
| 375 | |||
| 376 | try { |
||
| 377 | $templateProvider = $this->publicShareTemplateFactory->getProvider($share); |
||
| 378 | $response = $templateProvider->renderPage($share, $this->getToken(), $path); |
||
| 379 | } catch (NotFoundException $e) { |
||
| 380 | $this->emitAccessShareHook($share, 404, 'Share not found'); |
||
| 381 | $this->emitShareAccessEvent($share, ShareController::SHARE_ACCESS, 404, 'Share not found'); |
||
| 382 | throw new NotFoundException(); |
||
| 383 | } |
||
| 384 | |||
| 385 | // We can't get the path of a file share |
||
| 386 | try { |
||
| 387 | if ($shareNode instanceof \OCP\Files\File && $path !== '') { |
||
| 388 | $this->emitAccessShareHook($share, 404, 'Share not found'); |
||
| 389 | $this->emitShareAccessEvent($share, self::SHARE_ACCESS, 404, 'Share not found'); |
||
| 390 | throw new NotFoundException(); |
||
| 391 | } |
||
| 392 | } catch (\Exception $e) { |
||
| 393 | $this->emitAccessShareHook($share, 404, 'Share not found'); |
||
| 394 | $this->emitShareAccessEvent($share, self::SHARE_ACCESS, 404, 'Share not found'); |
||
| 395 | throw $e; |
||
| 396 | } |
||
| 397 | |||
| 398 | |||
| 399 | $this->emitAccessShareHook($share); |
||
| 400 | $this->emitShareAccessEvent($share, self::SHARE_ACCESS); |
||
| 401 | |||
| 402 | return $response; |
||
| 403 | } |
||
| 404 | |||
| 405 | /** |
||
| 406 | * @PublicPage |
||
| 407 | * @NoCSRFRequired |
||
| 408 | * @NoSameSiteCookieRequired |
||
| 409 | * |
||
| 410 | * @param string $token |
||
| 411 | * @param string $files |
||
| 412 | * @param string $path |
||
| 413 | * @param string $downloadStartSecret |
||
| 414 | * @return void|\OCP\AppFramework\Http\Response |
||
| 415 | * @throws NotFoundException |
||
| 416 | */ |
||
| 417 | public function downloadShare($token, $files = null, $path = '', $downloadStartSecret = '') { |
||
| 418 | \OC_User::setIncognitoMode(true); |
||
| 419 | |||
| 420 | $share = $this->shareManager->getShareByToken($token); |
||
| 421 | |||
| 422 | if (!($share->getPermissions() & \OCP\Constants::PERMISSION_READ)) { |
||
| 423 | return new \OCP\AppFramework\Http\DataResponse('Share has no read permission'); |
||
| 424 | } |
||
| 425 | |||
| 426 | $files_list = null; |
||
| 427 | if (!is_null($files)) { // download selected files |
||
| 428 | $files_list = json_decode($files); |
||
| 429 | // in case we get only a single file |
||
| 430 | if ($files_list === null) { |
||
| 431 | $files_list = [$files]; |
||
| 432 | } |
||
| 433 | // Just in case $files is a single int like '1234' |
||
| 434 | if (!is_array($files_list)) { |
||
| 435 | $files_list = [$files_list]; |
||
| 436 | } |
||
| 437 | } |
||
| 438 | |||
| 439 | if (!$this->validateShare($share)) { |
||
| 440 | throw new NotFoundException(); |
||
| 441 | } |
||
| 442 | |||
| 443 | $userFolder = $this->rootFolder->getUserFolder($share->getShareOwner()); |
||
| 444 | $originalSharePath = $userFolder->getRelativePath($share->getNode()->getPath()); |
||
| 445 | |||
| 446 | |||
| 447 | // Single file share |
||
| 448 | if ($share->getNode() instanceof \OCP\Files\File) { |
||
| 449 | // Single file download |
||
| 450 | $this->singleFileDownloaded($share, $share->getNode()); |
||
| 451 | } |
||
| 452 | // Directory share |
||
| 453 | else { |
||
| 454 | /** @var \OCP\Files\Folder $node */ |
||
| 455 | $node = $share->getNode(); |
||
| 456 | |||
| 457 | // Try to get the path |
||
| 458 | if ($path !== '') { |
||
| 459 | try { |
||
| 460 | $node = $node->get($path); |
||
| 461 | } catch (NotFoundException $e) { |
||
| 462 | $this->emitAccessShareHook($share, 404, 'Share not found'); |
||
| 463 | $this->emitShareAccessEvent($share, self::SHARE_DOWNLOAD, 404, 'Share not found'); |
||
| 464 | return new NotFoundResponse(); |
||
| 465 | } |
||
| 466 | } |
||
| 467 | |||
| 468 | $originalSharePath = $userFolder->getRelativePath($node->getPath()); |
||
| 469 | |||
| 470 | if ($node instanceof \OCP\Files\File) { |
||
| 471 | // Single file download |
||
| 472 | $this->singleFileDownloaded($share, $share->getNode()); |
||
| 473 | } else { |
||
| 474 | try { |
||
| 475 | if (!empty($files_list)) { |
||
| 476 | $this->fileListDownloaded($share, $files_list, $node); |
||
| 477 | } else { |
||
| 478 | // The folder is downloaded |
||
| 479 | $this->singleFileDownloaded($share, $share->getNode()); |
||
| 480 | } |
||
| 481 | } catch (NotFoundException $e) { |
||
| 482 | return new NotFoundResponse(); |
||
| 483 | } |
||
| 484 | } |
||
| 485 | } |
||
| 486 | |||
| 487 | /* FIXME: We should do this all nicely in OCP */ |
||
| 488 | OC_Util::tearDownFS(); |
||
| 489 | OC_Util::setupFS($share->getShareOwner()); |
||
| 490 | |||
| 491 | /** |
||
| 492 | * this sets a cookie to be able to recognize the start of the download |
||
| 493 | * the content must not be longer than 32 characters and must only contain |
||
| 494 | * alphanumeric characters |
||
| 495 | */ |
||
| 496 | if (!empty($downloadStartSecret) |
||
| 497 | && !isset($downloadStartSecret[32]) |
||
| 498 | && preg_match('!^[a-zA-Z0-9]+$!', $downloadStartSecret) === 1) { |
||
| 499 | |||
| 500 | // FIXME: set on the response once we use an actual app framework response |
||
| 501 | setcookie('ocDownloadStarted', $downloadStartSecret, time() + 20, '/'); |
||
| 502 | } |
||
| 503 | |||
| 504 | $this->emitAccessShareHook($share); |
||
| 505 | $this->emitShareAccessEvent($share, self::SHARE_DOWNLOAD); |
||
| 506 | |||
| 507 | $server_params = [ 'head' => $this->request->getMethod() === 'HEAD' ]; |
||
| 508 | |||
| 509 | /** |
||
| 510 | * Http range requests support |
||
| 511 | */ |
||
| 512 | if (isset($_SERVER['HTTP_RANGE'])) { |
||
| 513 | $server_params['range'] = $this->request->getHeader('Range'); |
||
| 514 | } |
||
| 515 | |||
| 516 | // download selected files |
||
| 517 | if (!is_null($files) && $files !== '') { |
||
| 518 | // FIXME: The exit is required here because otherwise the AppFramework is trying to add headers as well |
||
| 519 | // after dispatching the request which results in a "Cannot modify header information" notice. |
||
| 520 | OC_Files::get($originalSharePath, $files_list, $server_params); |
||
| 521 | exit(); |
||
| 522 | } else { |
||
| 523 | // FIXME: The exit is required here because otherwise the AppFramework is trying to add headers as well |
||
| 524 | // after dispatching the request which results in a "Cannot modify header information" notice. |
||
| 525 | OC_Files::get(dirname($originalSharePath), basename($originalSharePath), $server_params); |
||
| 526 | exit(); |
||
| 527 | } |
||
| 528 | } |
||
| 529 | |||
| 530 | /** |
||
| 531 | * create activity for every downloaded file |
||
| 532 | * |
||
| 533 | * @param Share\IShare $share |
||
| 534 | * @param array $files_list |
||
| 535 | * @param \OCP\Files\Folder $node |
||
| 536 | * @throws NotFoundException when trying to download a folder or multiple files of a "hide download" share |
||
| 537 | */ |
||
| 538 | protected function fileListDownloaded(Share\IShare $share, array $files_list, \OCP\Files\Folder $node) { |
||
| 539 | if ($share->getHideDownload() && count($files_list) > 1) { |
||
| 540 | throw new NotFoundException('Downloading more than 1 file'); |
||
| 541 | } |
||
| 542 | |||
| 543 | foreach ($files_list as $file) { |
||
| 544 | $subNode = $node->get($file); |
||
| 545 | $this->singleFileDownloaded($share, $subNode); |
||
| 546 | } |
||
| 547 | } |
||
| 548 | |||
| 549 | /** |
||
| 550 | * create activity if a single file was downloaded from a link share |
||
| 551 | * |
||
| 552 | * @param Share\IShare $share |
||
| 553 | * @throws NotFoundException when trying to download a folder of a "hide download" share |
||
| 554 | */ |
||
| 555 | protected function singleFileDownloaded(Share\IShare $share, \OCP\Files\Node $node) { |
||
| 556 | if ($share->getHideDownload() && $node instanceof Folder) { |
||
| 557 | throw new NotFoundException('Downloading a folder'); |
||
| 558 | } |
||
| 559 | |||
| 560 | $fileId = $node->getId(); |
||
| 561 | |||
| 562 | $userFolder = $this->rootFolder->getUserFolder($share->getSharedBy()); |
||
| 563 | $userNodeList = $userFolder->getById($fileId); |
||
| 564 | $userNode = $userNodeList[0]; |
||
| 565 | $ownerFolder = $this->rootFolder->getUserFolder($share->getShareOwner()); |
||
| 566 | $userPath = $userFolder->getRelativePath($userNode->getPath()); |
||
| 567 | $ownerPath = $ownerFolder->getRelativePath($node->getPath()); |
||
| 568 | $remoteAddress = $this->request->getRemoteAddress(); |
||
| 569 | $dateTime = new \DateTime(); |
||
| 570 | $dateTime = $dateTime->format('Y-m-d H'); |
||
| 571 | $remoteAddressHash = md5($dateTime . '-' . $remoteAddress); |
||
| 572 | |||
| 573 | $parameters = [$userPath]; |
||
| 574 | |||
| 575 | if ($share->getShareType() === IShare::TYPE_EMAIL) { |
||
| 576 | if ($node instanceof \OCP\Files\File) { |
||
| 577 | $subject = Downloads::SUBJECT_SHARED_FILE_BY_EMAIL_DOWNLOADED; |
||
| 578 | } else { |
||
| 579 | $subject = Downloads::SUBJECT_SHARED_FOLDER_BY_EMAIL_DOWNLOADED; |
||
| 580 | } |
||
| 581 | $parameters[] = $share->getSharedWith(); |
||
| 582 | } else { |
||
| 583 | if ($node instanceof \OCP\Files\File) { |
||
| 584 | $subject = Downloads::SUBJECT_PUBLIC_SHARED_FILE_DOWNLOADED; |
||
| 585 | $parameters[] = $remoteAddressHash; |
||
| 586 | } else { |
||
| 587 | $subject = Downloads::SUBJECT_PUBLIC_SHARED_FOLDER_DOWNLOADED; |
||
| 588 | $parameters[] = $remoteAddressHash; |
||
| 589 | } |
||
| 590 | } |
||
| 591 | |||
| 592 | $this->publishActivity($subject, $parameters, $share->getSharedBy(), $fileId, $userPath); |
||
| 593 | |||
| 594 | if ($share->getShareOwner() !== $share->getSharedBy()) { |
||
| 595 | $parameters[0] = $ownerPath; |
||
| 596 | $this->publishActivity($subject, $parameters, $share->getShareOwner(), $fileId, $ownerPath); |
||
| 597 | } |
||
| 598 | } |
||
| 599 | |||
| 600 | /** |
||
| 601 | * publish activity |
||
| 602 | * |
||
| 603 | * @param string $subject |
||
| 604 | * @param array $parameters |
||
| 605 | * @param string $affectedUser |
||
| 606 | * @param int $fileId |
||
| 607 | * @param string $filePath |
||
| 608 | */ |
||
| 609 | protected function publishActivity($subject, |
||
| 621 | } |
||
| 622 | } |
||
| 623 |
The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g.
excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths